diff --git a/.github/workflows/main.yaml b/.github/workflows/update-remote-database.yaml
similarity index 87%
rename from .github/workflows/main.yaml
rename to .github/workflows/update-remote-database.yaml
index 51cce57..93e8996 100644
--- a/.github/workflows/main.yaml
+++ b/.github/workflows/update-remote-database.yaml
@@ -1,4 +1,4 @@
-name: Release (Production)
+name: Update Remote Database
on:
push:
@@ -21,4 +21,4 @@ jobs:
version: latest
- run: supabase link --project-ref $SUPABASE_PROJECT_ID
- - run: supabase db push
\ No newline at end of file
+ - run: supabase db push --include-all
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..6c6067f
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1 @@
+supabase/migrations
\ No newline at end of file
diff --git a/.prettierrc.json b/.prettierrc.json
new file mode 100644
index 0000000..93c54d9
--- /dev/null
+++ b/.prettierrc.json
@@ -0,0 +1,21 @@
+{
+ "semi": true,
+ "trailingComma": "all",
+ "singleQuote": true,
+ "printWidth": 80,
+ "tabWidth": 2,
+ "useTabs": false,
+ "jsxSingleQuote": false,
+ "arrowParens": "always",
+ "plugins": ["prettier-plugin-sql"],
+ "overrides": [
+ {
+ "files": "*.sql",
+ "options": {
+ "language": "postgresql",
+ "keywordCase": "lower",
+ "dataTypeCase": "lower"
+ }
+ }
+ ]
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..9bf4d12
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,4 @@
+{
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
+ "editor.formatOnSave": true
+}
diff --git a/app/(pages)/example/page.tsx b/app/(pages)/example/page.tsx
deleted file mode 100644
index bffadf2..0000000
--- a/app/(pages)/example/page.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-"use client";
-
-import { createExampleEntry } from "@/app/api/example/actions";
-import { ExampleType } from "@/app/types/ExampleType";
-
-export default function Example() {
- const data: ExampleType = {
- id: 5,
- name: 'harry',
- };
-
- const handleExampleClick = async () => {
- await createExampleEntry(data);
- };
-
- return (
-
- Welcome to PATH! This is an example page.
-
-
- Click to add data to the example table
-
-
- );
-}
\ No newline at end of file
diff --git a/app/(pages)/test/page.tsx b/app/(pages)/test/page.tsx
new file mode 100644
index 0000000..3a3df0a
--- /dev/null
+++ b/app/(pages)/test/page.tsx
@@ -0,0 +1,23 @@
+'use client';
+
+import ExampleTestComponent from '@/app/components/test/ExampleTestComponent';
+import DonationsTestComponent from '@/app/components/test/DonationsTestComponent';
+import StoresTestComponent from '@/app/components/test/StoresTestComponent';
+import InventoryItemsTestComponent from '@/app/components/test/InventoryItemsTestComponent';
+import TicketsTestComponent from '@/app/components/test/TicketsTestComponent';
+import TicketItemsTestComponent from '@/app/components/test/TicketItemsTestComponent';
+
+export default function TestPage() {
+ return (
+
+ Welcome to PATH! This is a test page.
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/app/api/donations/actions.ts b/app/api/donations/actions.ts
new file mode 100644
index 0000000..2260a0b
--- /dev/null
+++ b/app/api/donations/actions.ts
@@ -0,0 +1,36 @@
+'use server';
+
+import { DonationInsert } from '@/app/types/donation';
+import { createClient } from '@/app/lib/supabase/server-client';
+
+export async function createDonation(data: DonationInsert) {
+ const supabase = await createClient();
+
+ const { data: entry, error: err } = await supabase
+ .from('donations')
+ .insert(data)
+ .select() // after inserting, return full new row
+ .single(); // expect just one row, if more or less, throw an error
+
+ if (err) {
+ console.error('Error creating donation:', err);
+ return { success: false, error: err };
+ }
+ return { success: true, data: entry }; // return the row that was created
+}
+
+// deletes donation based on donation_id
+export async function deleteDonation(donationId: string) {
+ const supabase = await createClient();
+
+ const { error: err } = await supabase
+ .from('donations')
+ .delete()
+ .eq('donation_id', donationId);
+
+ if (err) {
+ console.error('Error deleting donation:', err);
+ return { success: false, error: err };
+ }
+ return { success: true };
+}
diff --git a/app/api/example/actions.ts b/app/api/example/actions.ts
index db2c0cb..3d5b37d 100644
--- a/app/api/example/actions.ts
+++ b/app/api/example/actions.ts
@@ -1,14 +1,19 @@
-"use server";
+'use server';
-import { ExampleType } from "@/app/types/ExampleType";
-import { createClient } from "@/app/lib/supabase/server-client";
+import { Example } from '@/app/types/example';
+import { createClient } from '@/app/lib/supabase/server-client';
-export const createExampleEntry = async (data: ExampleType) => {
+export const createExampleEntry = async (data: Example) => {
const supabase = await createClient();
- const { data: entry, error } = await supabase.from("example").insert(data);
+ const { data: entry, error: err } = await supabase
+ .from('example')
+ .insert(data)
+ .select()
+ .single();
- if (error) {
- throw error;
+ if (err) {
+ console.error('Error creating example:', err);
+ return { success: false, error: err };
}
- return entry;
-}
\ No newline at end of file
+ return { success: true, data: entry };
+};
diff --git a/app/api/inventory-items/actions.ts b/app/api/inventory-items/actions.ts
new file mode 100644
index 0000000..0004462
--- /dev/null
+++ b/app/api/inventory-items/actions.ts
@@ -0,0 +1,50 @@
+'use server';
+
+import { InventoryItemInsert } from '@/app/types/inventory';
+import { createClient } from '@/app/lib/supabase/server-client';
+
+export const createItem = async (data: InventoryItemInsert) => {
+ const supabase = await createClient();
+ const { data: entry, error: err } = await supabase
+ .from('inventory_items')
+ .insert(data)
+ .select()
+ .single();
+
+ if (err) {
+ console.error('Error creating inventory item:', err);
+ return { success: false, error: err };
+ }
+ return { success: true, data: entry };
+};
+
+export const changeItemQuantity = async (
+ inventoryItemId: string,
+ newQuantity: number,
+) => {
+ const supabase = await createClient();
+ const { error: err } = await supabase
+ .from('inventory_items')
+ .update({ quantity_available: newQuantity })
+ .eq('inventory_item_id', inventoryItemId);
+
+ if (err) {
+ console.error('Error changing inventory item quantity:', err);
+ return { success: false, error: err };
+ }
+ return { success: true };
+};
+
+export const deleteItem = async (inventoryItemId: string) => {
+ const supabase = await createClient();
+ const { error: err } = await supabase
+ .from('inventory_items')
+ .delete()
+ .eq('inventory_item_id', inventoryItemId);
+
+ if (err) {
+ console.error('Error deleting inventory item:', err);
+ return { success: false, error: err };
+ }
+ return { success: true };
+};
diff --git a/app/api/stores/actions.ts b/app/api/stores/actions.ts
new file mode 100644
index 0000000..0fb4718
--- /dev/null
+++ b/app/api/stores/actions.ts
@@ -0,0 +1,35 @@
+'use server';
+
+import { createClient } from '@/app/lib/supabase/server-client';
+import { StoreInsert } from '@/app/types/store';
+
+// create store
+export const createStore = async (data: StoreInsert) => {
+ const supabase = await createClient();
+ const { data: entry, error: err } = await supabase
+ .from('stores')
+ .insert(data)
+ .select()
+ .single();
+
+ if (err) {
+ console.error('Error creating store:', err);
+ return { success: false, error: err };
+ }
+ return { success: true, data: entry };
+};
+
+// delete store given store_id
+export const deleteStore = async (storeId: string) => {
+ const supabase = await createClient();
+ const { error: err } = await supabase
+ .from('stores')
+ .delete()
+ .eq('store_id', storeId);
+
+ if (err) {
+ console.error('Error deleting store:', err);
+ return { success: false, error: err };
+ }
+ return { success: true };
+};
diff --git a/app/api/ticket-items/actions.ts b/app/api/ticket-items/actions.ts
new file mode 100644
index 0000000..4404e09
--- /dev/null
+++ b/app/api/ticket-items/actions.ts
@@ -0,0 +1,68 @@
+'use server';
+
+import { TicketItemInsert } from '@/app/types/ticket';
+import { createClient } from '@/app/lib/supabase/server-client';
+
+export async function createTicketItem(data: TicketItemInsert) {
+ const supabase = await createClient();
+ // Server Action uses a mutation method
+ const { data: entry, error: err } = await supabase
+ .from('ticket_items')
+ .insert(data)
+ .select()
+ .single();
+
+ if (err) {
+ console.error('Error creating ticket item:', err);
+ return { success: false, error: err };
+ }
+ return { success: true, data: entry };
+}
+
+export async function changeTicketItemQuantity(
+ ticketItemId: string,
+ newQuantity: number,
+) {
+ const supabase = await createClient();
+ const { error: err } = await supabase
+ .from('ticket_items')
+ .update({ quantity_requested: newQuantity })
+ .eq('ticket_item_id', ticketItemId);
+
+ if (err) {
+ console.error('Error changing ticket item quantity:', err);
+ return { success: false, error: err };
+ }
+ return { success: true };
+}
+
+export async function changeTicketItemDescription(
+ ticketItemId: string,
+ newDescription: string,
+) {
+ const supabase = await createClient();
+ const { error: err } = await supabase
+ .from('ticket_items')
+ .update({ free_text_description: newDescription })
+ .eq('ticket_item_id', ticketItemId);
+
+ if (err) {
+ console.error('Error changing ticket item description:', err);
+ return { success: false, error: err };
+ }
+ return { success: true };
+}
+
+export async function deleteTicketItem(ticketItemId: string) {
+ const supabase = await createClient();
+ const { error: err } = await supabase
+ .from('ticket_items')
+ .delete()
+ .eq('ticket_item_id', ticketItemId);
+
+ if (err) {
+ console.error('Error deleting ticket item:', err);
+ return { success: false, error: err };
+ }
+ return { success: true };
+}
diff --git a/app/api/tickets/actions.ts b/app/api/tickets/actions.ts
new file mode 100644
index 0000000..cdb96f8
--- /dev/null
+++ b/app/api/tickets/actions.ts
@@ -0,0 +1,48 @@
+'use server'; // directive that indicates that the functions we define are server actions
+
+import { TicketInsert } from '@/app/types/ticket';
+import { createClient } from '@/app/lib/supabase/server-client';
+
+export async function createTicket(data: TicketInsert) {
+ const supabase = await createClient();
+ // pulling out the error from the insert into tickets table
+ const { data: entry, error: err } = await supabase
+ .from('tickets')
+ .insert(data)
+ .select()
+ .single();
+
+ if (err) {
+ console.error('Error creating ticket:', err);
+ return { success: false, error: err };
+ }
+ return { success: true, data: entry };
+}
+
+export async function deleteTicket(ticketId: string) {
+ const supabase = await createClient();
+ const { error: err } = await supabase
+ .from('tickets')
+ .delete()
+ .eq('ticket_id', ticketId);
+
+ if (err) {
+ console.error('Error deleting ticket:', err);
+ return { success: false, error: err };
+ }
+ return { success: true };
+}
+
+export async function updateTicketStatus(newStatus: string, ticketId: string) {
+ const supabase = await createClient();
+ const { error: err } = await supabase
+ .from('tickets')
+ .update({ status: newStatus })
+ .eq('ticket_id', ticketId);
+
+ if (err) {
+ console.error('Error changing ticket status:', err);
+ return { success: false, error: err };
+ }
+ return { success: true };
+}
diff --git a/app/components/test/DonationsTestComponent.tsx b/app/components/test/DonationsTestComponent.tsx
new file mode 100644
index 0000000..97577a3
--- /dev/null
+++ b/app/components/test/DonationsTestComponent.tsx
@@ -0,0 +1,50 @@
+'use client';
+
+import { createDonation, deleteDonation } from '@/app/api/donations/actions';
+
+export default function DonationsTestComponent() {
+ const handleCreate = async () => {
+ try {
+ const donation = await createDonation({
+ receiver_user_id: '00000000-0000-0000-0000-000000000000',
+ store_id: null,
+ donor_is_individual: true,
+ donor_individual_name: 'Test User',
+ donor_business_name: 'Donor Business Name',
+ donor_business_contact_name: 'Ms. Donor',
+ donor_email: 'test@example.com',
+ donor_phone: '123-456-7890',
+ donor_street_address: '1234 Bruin Ave',
+ donor_receive_mailings: false,
+ donor_receive_emails: true,
+ donor_remain_anonymous: false,
+ estimated_value: 50,
+ items_donated: 'Items donated!',
+ });
+
+ console.log('Created donation:', donation);
+ } catch (err) {
+ console.error('Create failed:', err);
+ }
+ };
+
+ const handleDelete = async () => {
+ const idToDelete = '40b188ab-e9a1-444d-9e6b-6b99d5017c90'; // hard-coded ID for now
+ try {
+ const result = await deleteDonation(idToDelete);
+ console.log('Deleted donation:', result);
+ } catch (err) {
+ console.error('Delete failed:', err);
+ }
+ };
+
+ return (
+
+
Test Donations
+ Create Donation
+
+ Delete Donation
+
+
+ );
+}
diff --git a/app/components/test/ExampleTestComponent.tsx b/app/components/test/ExampleTestComponent.tsx
new file mode 100644
index 0000000..0831c41
--- /dev/null
+++ b/app/components/test/ExampleTestComponent.tsx
@@ -0,0 +1,21 @@
+'use client';
+
+import { createExampleEntry } from '@/app/api/example/actions';
+import { Example } from '@/app/types/example';
+
+export default function ExampleTestComponent() {
+ const data: Example = {
+ id: 5,
+ name: 'harry',
+ };
+
+ const handleExampleClick = async () => {
+ await createExampleEntry(data);
+ };
+
+ return (
+
+ Click to add data to the example table
+
+ );
+}
diff --git a/app/components/test/InventoryItemsTestComponent.tsx b/app/components/test/InventoryItemsTestComponent.tsx
new file mode 100644
index 0000000..9cc69ad
--- /dev/null
+++ b/app/components/test/InventoryItemsTestComponent.tsx
@@ -0,0 +1,90 @@
+'use client';
+
+import { useState } from 'react';
+import type { InventoryItemInsert } from '@/app/types/inventory';
+import {
+ createItem,
+ changeItemQuantity,
+ deleteItem,
+} from '@/app/api/inventory-items/actions';
+
+export default function InventoryItemsTestComponent() {
+ const [inventoryId, setInventoryId] = useState('');
+ const [inventoryIdToDelete, setInventoryIdToDelete] = useState('');
+ const [updatedQuantity, setUpdatedQuantity] = useState(0);
+
+ const data: InventoryItemInsert = {
+ store_id: '4c7b2b65-16df-44b5-a3c2-e2fcd090b76c',
+ subcategory_id: 1,
+ item: 'Sample Item',
+ description: 'test description',
+ photo_url: 'http://example.com/photo.jpg',
+ quantity_available: 2,
+ is_hidden: false,
+ };
+
+ const handleCreateItem = async () => {
+ await createItem(data);
+ };
+
+ const handleChangeItemQuantity = async () => {
+ await changeItemQuantity(inventoryId, Number(updatedQuantity));
+ };
+
+ const handleDeleteItem = async () => {
+ await deleteItem(inventoryIdToDelete);
+ };
+
+ return (
+
+
+
Create an Item
+
Click to add inventory item
+
+
+
Update an Item
+
+
+ Inventory Item ID to Update:
+ setInventoryId(e.target.value)}
+ placeholder="inventory_item_id"
+ />
+
+
+
+ New Quantity:
+ setUpdatedQuantity(Number(e.target.value))}
+ placeholder="0"
+ min={0}
+ />
+
+
+
+ Update inventory quantity
+
+
+
+
Delete an Item
+
+
+ Inventory Item ID to Delete:
+ setInventoryIdToDelete(e.target.value)}
+ placeholder="inventory_item_id"
+ />
+
+
+ Delete inventory item
+
+
+
+ );
+}
diff --git a/app/components/test/StoresTestComponent.tsx b/app/components/test/StoresTestComponent.tsx
new file mode 100644
index 0000000..a971406
--- /dev/null
+++ b/app/components/test/StoresTestComponent.tsx
@@ -0,0 +1,30 @@
+'use client';
+
+import { createStore, deleteStore } from '@/app/api/stores/actions';
+import { StoreInsert } from '@/app/types/store';
+
+export default function StoresTestComponent() {
+ const storeData: StoreInsert = {
+ name: 'test store',
+ street_address: 'test address',
+ };
+
+ const handleAddStoreClick = async () => {
+ await createStore(storeData);
+ };
+
+ const handleDeleteStoreClick = async () => {
+ await deleteStore('ea9a0fac-c881-4740-894c-34139859a057');
+ };
+
+ return (
+
+
+ Click to add store to stores table
+
+
+ Click to delete store from stores table
+
+
+ );
+}
diff --git a/app/components/test/TicketItemsTestComponent.tsx b/app/components/test/TicketItemsTestComponent.tsx
new file mode 100644
index 0000000..fe7929a
--- /dev/null
+++ b/app/components/test/TicketItemsTestComponent.tsx
@@ -0,0 +1,48 @@
+'use client';
+
+import {
+ createTicketItem,
+ changeTicketItemDescription,
+ changeTicketItemQuantity,
+ deleteTicketItem,
+} from '@/app/api/ticket-items/actions';
+import { TicketItemInsert } from '@/app/types/ticket';
+
+export default function TicketItemTestComponent() {
+ const data: TicketItemInsert = {
+ ticket_id: 'c088b0b7-e4c3-40ae-80ca-9d8376dbb4fa',
+ inventory_item_id: 'bec1fdd9-d6f0-4c49-aa2f-c67a18fc05f2',
+ free_text_description: 'sample description',
+ quantity_requested: 10,
+ is_in_stock_request: true,
+ };
+
+ const ticketItemId = '4a3e0f98-e17a-4891-9d7c-d72f44245adc';
+
+ const handleCreate = async () => {
+ await createTicketItem(data);
+ };
+
+ const handleDelete = async () => {
+ await deleteTicketItem(ticketItemId);
+ };
+
+ const handleChangeDescription = async () => {
+ await changeTicketItemDescription(ticketItemId, 'new description');
+ };
+
+ const handleChangeQuantity = async () => {
+ await changeTicketItemQuantity(ticketItemId, 5);
+ };
+
+ return (
+
+ Click to add ticket item
+ Click to delete ticket item
+
+ Click to modify description
+
+ Click to modify quantity
+
+ );
+}
diff --git a/app/components/test/TicketsTestComponent.tsx b/app/components/test/TicketsTestComponent.tsx
new file mode 100644
index 0000000..e4cb22d
--- /dev/null
+++ b/app/components/test/TicketsTestComponent.tsx
@@ -0,0 +1,83 @@
+'use client';
+
+import {
+ createTicket,
+ deleteTicket,
+ updateTicketStatus,
+} from '@/app/api/tickets/actions';
+import { useState } from 'react';
+import { TicketInsert } from '@/app/types/ticket';
+
+export default function TicketsTestComponent() {
+ const [ticketToDelete, setDelete] = useState('');
+ const [ticketToUpdate, setUpdateTicket] = useState('');
+ const [updateStatus, setStatus] = useState('');
+
+ const ticketData: TicketInsert = {
+ requestor_user_id: '4c4f3502-1b31-4040-8a7a-2baedbc8a347',
+ store_id: '94b6329f-7383-46e2-978d-e105d31c3813',
+ status: 'ready',
+ };
+
+ const submitTicket = async () => {
+ await createTicket(ticketData);
+ };
+
+ const sendTicketDeletion = async () => {
+ await deleteTicket(ticketToDelete);
+ };
+
+ const updateTicket = async () => {
+ await updateTicketStatus(updateStatus, ticketToUpdate);
+ };
+
+ return (
+
+
Ticket Testing
+
+ Click to add ticket to the ticket table
+
+
+
+ Ticket to delete:{' '}
+ {
+ setDelete(event.target.value);
+ }}
+ />
+
+
+
+ Click to delete ticket from the ticket table
+
+
+
+ Ticket to update:{' '}
+ {
+ setUpdateTicket(event.target.value);
+ }}
+ />
+
+
+
+ New Status:{' '}
+ {
+ setStatus(event.target.value);
+ }}
+ />
+
+
+ Click to update status of ticket
+
+
+
+ );
+}
diff --git a/app/globals.css b/app/globals.css
index dd085e1..581442c 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -1,4 +1,4 @@
-@import "tailwindcss";
+@import 'tailwindcss';
:root {
--background: #ffffff;
diff --git a/app/layout.tsx b/app/layout.tsx
index 735d2b7..7095646 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -1,9 +1,9 @@
-import type { Metadata } from "next";
-import "./globals.css";
+import type { Metadata } from 'next';
+import './globals.css';
export const metadata: Metadata = {
- title: "PATH App",
- description: "Resource management application for PATH",
+ title: 'PATH App',
+ description: 'Resource management application for PATH',
};
export default function RootLayout({
@@ -13,9 +13,7 @@ export default function RootLayout({
}>) {
return (
-
- {children}
-
+ {children}
);
}
diff --git a/app/lib/supabase/browser-client.ts b/app/lib/supabase/browser-client.ts
index 063c38d..7aab535 100644
--- a/app/lib/supabase/browser-client.ts
+++ b/app/lib/supabase/browser-client.ts
@@ -1,8 +1,8 @@
-import { createBrowserClient } from "@supabase/ssr";
+import { createBrowserClient } from '@supabase/ssr';
export function createClient() {
return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
- process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
+ process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
);
-}
\ No newline at end of file
+}
diff --git a/app/lib/supabase/server-client.ts b/app/lib/supabase/server-client.ts
index 2d239fa..421518b 100644
--- a/app/lib/supabase/server-client.ts
+++ b/app/lib/supabase/server-client.ts
@@ -1,5 +1,5 @@
-import { createServerClient } from "@supabase/ssr";
-import { cookies } from "next/headers";
+import { createServerClient } from '@supabase/ssr';
+import { cookies } from 'next/headers';
export async function createClient() {
const cookieStore = await cookies();
return createServerClient(
@@ -13,13 +13,13 @@ export async function createClient() {
setAll(cookiesToSet) {
try {
cookiesToSet.forEach(({ name, value, options }) =>
- cookieStore.set(name, value, options)
+ cookieStore.set(name, value, options),
);
} catch {
- throw new Error("Cookies are not available");
+ throw new Error('Cookies are not available');
}
},
},
- }
+ },
);
-}
\ No newline at end of file
+}
diff --git a/app/page.tsx b/app/page.tsx
index 1d25e78..050e73b 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -1,14 +1,14 @@
-"use client";
+'use client';
-import { useEffect } from "react";
-import { useRouter } from "next/navigation";
+import { useEffect } from 'react';
+import { useRouter } from 'next/navigation';
export default function Home() {
const router = useRouter();
useEffect(() => {
// replace() avoids adding to browser history
- router.replace("/example");
+ router.replace('/test');
}, [router]);
return null;
-}
\ No newline at end of file
+}
diff --git a/app/types/donation.ts b/app/types/donation.ts
new file mode 100644
index 0000000..8909d9e
--- /dev/null
+++ b/app/types/donation.ts
@@ -0,0 +1,25 @@
+export type Donation = {
+ donation_id: string; // generated by database
+ receiver_user_id: string;
+ store_id?: string | null;
+
+ date_submitted: Date | string; // generated by default
+ donor_is_individual: boolean;
+
+ donor_individual_name?: string | null; // optional
+ donor_business_name?: string | null; // optional
+ donor_business_contact_name?: string | null; // optional
+
+ donor_email: string;
+ donor_phone?: string | null; // optional
+
+ donor_street_address?: string | null; // optional
+ donor_receive_mailings: boolean;
+ donor_receive_emails: boolean;
+ donor_remain_anonymous: boolean;
+
+ estimated_value: number;
+ items_donated: string;
+};
+
+export type DonationInsert = Omit;
diff --git a/app/types/ExampleType.ts b/app/types/example.ts
similarity index 50%
rename from app/types/ExampleType.ts
rename to app/types/example.ts
index 42ecc61..3e3a313 100644
--- a/app/types/ExampleType.ts
+++ b/app/types/example.ts
@@ -1,4 +1,4 @@
-export type ExampleType = {
+export type Example = {
id: number;
name: string;
-};
\ No newline at end of file
+};
diff --git a/app/types/inventory.ts b/app/types/inventory.ts
new file mode 100644
index 0000000..adf17ad
--- /dev/null
+++ b/app/types/inventory.ts
@@ -0,0 +1,14 @@
+export type InventoryItem = {
+ inventory_item_id: string; // UUID
+ store_id: string; // UUID
+ subcategory_id: number;
+ item: string;
+ description: string;
+ photo_url?: string | null;
+ quantity_available: number;
+ is_hidden: boolean;
+};
+
+export type InventoryItemUpdate = Partial;
+
+export type InventoryItemInsert = Omit;
diff --git a/app/types/store.ts b/app/types/store.ts
new file mode 100644
index 0000000..0e2abcb
--- /dev/null
+++ b/app/types/store.ts
@@ -0,0 +1,7 @@
+export type Store = {
+ store_id: string;
+ name: string;
+ street_address: string;
+};
+
+export type StoreInsert = Omit;
diff --git a/app/types/ticket.ts b/app/types/ticket.ts
new file mode 100644
index 0000000..92f5b7c
--- /dev/null
+++ b/app/types/ticket.ts
@@ -0,0 +1,24 @@
+export type Ticket = {
+ ticket_id: string; // string corresponds to uuid
+ requestor_user_id: string;
+ store_id: string;
+ status: string; // string corresponds to varchar
+ date_submitted: Date | string; // Date | string corresponds to time stamp with time zone
+};
+
+export type TicketUpdate = Partial;
+
+export type TicketInsert = Omit;
+
+export type TicketItem = {
+ ticket_item_id: string;
+ ticket_id: string;
+ inventory_item_id?: string | null;
+ free_text_description?: string | null;
+ quantity_requested?: number | null;
+ is_in_stock_request: boolean;
+};
+
+export type TicketItemUpdate = Partial;
+
+export type TicketItemInsert = Omit;
diff --git a/eslint.config.mjs b/eslint.config.mjs
index 05e726d..386b0bc 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -1,17 +1,19 @@
-import { defineConfig, globalIgnores } from "eslint/config";
-import nextVitals from "eslint-config-next/core-web-vitals";
-import nextTs from "eslint-config-next/typescript";
+import { defineConfig, globalIgnores } from 'eslint/config';
+import nextVitals from 'eslint-config-next/core-web-vitals';
+import nextTs from 'eslint-config-next/typescript';
+import prettier from 'eslint-config-prettier/flat';
const eslintConfig = defineConfig([
...nextVitals,
...nextTs,
+ prettier,
// Override default ignores of eslint-config-next.
globalIgnores([
// Default ignores of eslint-config-next:
- ".next/**",
- "out/**",
- "build/**",
- "next-env.d.ts",
+ '.next/**',
+ 'out/**',
+ 'build/**',
+ 'next-env.d.ts',
]),
]);
diff --git a/next.config.ts b/next.config.ts
index e9ffa30..5e891cf 100644
--- a/next.config.ts
+++ b/next.config.ts
@@ -1,4 +1,4 @@
-import type { NextConfig } from "next";
+import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
/* config options here */
diff --git a/package-lock.json b/package-lock.json
index a7a5582..54b511a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,7 +10,7 @@
"dependencies": {
"@supabase/ssr": "^0.7.0",
"@supabase/supabase-js": "^2.81.1",
- "next": "16.0.1",
+ "next": "^16.0.7",
"react": "19.2.0",
"react-dom": "19.2.0"
},
@@ -21,6 +21,9 @@
"@types/react-dom": "^19",
"eslint": "^9",
"eslint-config-next": "16.0.1",
+ "eslint-config-prettier": "^10.1.8",
+ "prettier": "^3.7.4",
+ "prettier-plugin-sql": "^0.19.2",
"supabase": "^2.58.5",
"tailwindcss": "^4",
"typescript": "^5"
@@ -1051,9 +1054,9 @@
}
},
"node_modules/@next/env": {
- "version": "16.0.1",
- "resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.1.tgz",
- "integrity": "sha512-LFvlK0TG2L3fEOX77OC35KowL8D7DlFF45C0OvKMC4hy8c/md1RC4UMNDlUGJqfCoCS2VWrZ4dSE6OjaX5+8mw==",
+ "version": "16.0.10",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.10.tgz",
+ "integrity": "sha512-8tuaQkyDVgeONQ1MeT9Mkk8pQmZapMKFh5B+OrFUlG3rVmYTXcXlBetBgTurKXGaIZvkoqRT9JL5K3phXcgang==",
"license": "MIT"
},
"node_modules/@next/eslint-plugin-next": {
@@ -1067,9 +1070,9 @@
}
},
"node_modules/@next/swc-darwin-arm64": {
- "version": "16.0.1",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.0.1.tgz",
- "integrity": "sha512-R0YxRp6/4W7yG1nKbfu41bp3d96a0EalonQXiMe+1H9GTHfKxGNCGFNWUho18avRBPsO8T3RmdWuzmfurlQPbg==",
+ "version": "16.0.10",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.0.10.tgz",
+ "integrity": "sha512-4XgdKtdVsaflErz+B5XeG0T5PeXKDdruDf3CRpnhN+8UebNa5N2H58+3GDgpn/9GBurrQ1uWW768FfscwYkJRg==",
"cpu": [
"arm64"
],
@@ -1083,9 +1086,9 @@
}
},
"node_modules/@next/swc-darwin-x64": {
- "version": "16.0.1",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.0.1.tgz",
- "integrity": "sha512-kETZBocRux3xITiZtOtVoVvXyQLB7VBxN7L6EPqgI5paZiUlnsgYv4q8diTNYeHmF9EiehydOBo20lTttCbHAg==",
+ "version": "16.0.10",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.0.10.tgz",
+ "integrity": "sha512-spbEObMvRKkQ3CkYVOME+ocPDFo5UqHb8EMTS78/0mQ+O1nqE8toHJVioZo4TvebATxgA8XMTHHrScPrn68OGw==",
"cpu": [
"x64"
],
@@ -1099,9 +1102,9 @@
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
- "version": "16.0.1",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.0.1.tgz",
- "integrity": "sha512-hWg3BtsxQuSKhfe0LunJoqxjO4NEpBmKkE+P2Sroos7yB//OOX3jD5ISP2wv8QdUwtRehMdwYz6VB50mY6hqAg==",
+ "version": "16.0.10",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.0.10.tgz",
+ "integrity": "sha512-uQtWE3X0iGB8apTIskOMi2w/MKONrPOUCi5yLO+v3O8Mb5c7K4Q5KD1jvTpTF5gJKa3VH/ijKjKUq9O9UhwOYw==",
"cpu": [
"arm64"
],
@@ -1115,9 +1118,9 @@
}
},
"node_modules/@next/swc-linux-arm64-musl": {
- "version": "16.0.1",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.0.1.tgz",
- "integrity": "sha512-UPnOvYg+fjAhP3b1iQStcYPWeBFRLrugEyK/lDKGk7kLNua8t5/DvDbAEFotfV1YfcOY6bru76qN9qnjLoyHCQ==",
+ "version": "16.0.10",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.0.10.tgz",
+ "integrity": "sha512-llA+hiDTrYvyWI21Z0L1GiXwjQaanPVQQwru5peOgtooeJ8qx3tlqRV2P7uH2pKQaUfHxI/WVarvI5oYgGxaTw==",
"cpu": [
"arm64"
],
@@ -1131,9 +1134,9 @@
}
},
"node_modules/@next/swc-linux-x64-gnu": {
- "version": "16.0.1",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.0.1.tgz",
- "integrity": "sha512-Et81SdWkcRqAJziIgFtsFyJizHoWne4fzJkvjd6V4wEkWTB4MX6J0uByUb0peiJQ4WeAt6GGmMszE5KrXK6WKg==",
+ "version": "16.0.10",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.0.10.tgz",
+ "integrity": "sha512-AK2q5H0+a9nsXbeZ3FZdMtbtu9jxW4R/NgzZ6+lrTm3d6Zb7jYrWcgjcpM1k8uuqlSy4xIyPR2YiuUr+wXsavA==",
"cpu": [
"x64"
],
@@ -1147,9 +1150,9 @@
}
},
"node_modules/@next/swc-linux-x64-musl": {
- "version": "16.0.1",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.0.1.tgz",
- "integrity": "sha512-qBbgYEBRrC1egcG03FZaVfVxrJm8wBl7vr8UFKplnxNRprctdP26xEv9nJ07Ggq4y1adwa0nz2mz83CELY7N6Q==",
+ "version": "16.0.10",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.0.10.tgz",
+ "integrity": "sha512-1TDG9PDKivNw5550S111gsO4RGennLVl9cipPhtkXIFVwo31YZ73nEbLjNC8qG3SgTz/QZyYyaFYMeY4BKZR/g==",
"cpu": [
"x64"
],
@@ -1163,9 +1166,9 @@
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
- "version": "16.0.1",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.0.1.tgz",
- "integrity": "sha512-cPuBjYP6I699/RdbHJonb3BiRNEDm5CKEBuJ6SD8k3oLam2fDRMKAvmrli4QMDgT2ixyRJ0+DTkiODbIQhRkeQ==",
+ "version": "16.0.10",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.0.10.tgz",
+ "integrity": "sha512-aEZIS4Hh32xdJQbHz121pyuVZniSNoqDVx1yIr2hy+ZwJGipeqnMZBJHyMxv2tiuAXGx6/xpTcQJ6btIiBjgmg==",
"cpu": [
"arm64"
],
@@ -1179,9 +1182,9 @@
}
},
"node_modules/@next/swc-win32-x64-msvc": {
- "version": "16.0.1",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.0.1.tgz",
- "integrity": "sha512-XeEUJsE4JYtfrXe/LaJn3z1pD19fK0Q6Er8Qoufi+HqvdO4LEPyCxLUt4rxA+4RfYo6S9gMlmzCMU2F+AatFqQ==",
+ "version": "16.0.10",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.0.10.tgz",
+ "integrity": "sha512-E+njfCoFLb01RAFEnGZn6ERoOqhK1Gl3Lfz1Kjnj0Ulfu7oJbuMyvBKNj/bw8XZnenHDASlygTjZICQW+rYW1Q==",
"cpu": [
"x64"
],
@@ -1661,6 +1664,13 @@
"undici-types": "~6.21.0"
}
},
+ "node_modules/@types/pegjs": {
+ "version": "0.10.6",
+ "resolved": "https://registry.npmjs.org/@types/pegjs/-/pegjs-0.10.6.tgz",
+ "integrity": "sha512-eLYXDbZWXh2uxf+w8sXS8d6KSoXTswfps6fvCUuVAGN8eRpfe7h9eSRydxiSJvo9Bf+GzifsDOr9TMQlmJdmkw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/phoenix": {
"version": "1.6.6",
"resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.6.tgz",
@@ -2579,6 +2589,16 @@
"baseline-browser-mapping": "dist/cli.js"
}
},
+ "node_modules/big-integer": {
+ "version": "1.6.52",
+ "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz",
+ "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==",
+ "dev": true,
+ "license": "Unlicense",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
"node_modules/bin-links": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/bin-links/-/bin-links-6.0.0.tgz",
@@ -2797,6 +2817,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -2984,6 +3011,13 @@
"node": ">=8"
}
},
+ "node_modules/discontinuous-range": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz",
+ "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/doctrine": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
@@ -3340,6 +3374,22 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/eslint-config-prettier": {
+ "version": "10.1.8",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz",
+ "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-config-prettier"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
"node_modules/eslint-import-resolver-node": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
@@ -4685,9 +4735,9 @@
"license": "MIT"
},
"node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4744,6 +4794,16 @@
"node": ">=6"
}
},
+ "node_modules/jsox": {
+ "version": "1.2.124",
+ "resolved": "https://registry.npmjs.org/jsox/-/jsox-1.2.124.tgz",
+ "integrity": "sha512-KwptI8xUfOt7qJ+P+2utrJIEHTgDjXpBsDhPSM4GDq++4by+LX9nUFee97QfRloGcMh5iA9Ha/4UCVZl7zWzuA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsox": "lib/cli.js"
+ }
+ },
"node_modules/jsx-ast-utils": {
"version": "3.3.5",
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
@@ -5201,6 +5261,13 @@
"node": ">= 18"
}
},
+ "node_modules/moo": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz",
+ "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -5249,13 +5316,36 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/nearley": {
+ "version": "2.20.1",
+ "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz",
+ "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "commander": "^2.19.0",
+ "moo": "^0.5.0",
+ "railroad-diagrams": "^1.0.0",
+ "randexp": "0.4.6"
+ },
+ "bin": {
+ "nearley-railroad": "bin/nearley-railroad.js",
+ "nearley-test": "bin/nearley-test.js",
+ "nearley-unparse": "bin/nearley-unparse.js",
+ "nearleyc": "bin/nearleyc.js"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://nearley.js.org/#give-to-nearley"
+ }
+ },
"node_modules/next": {
- "version": "16.0.1",
- "resolved": "https://registry.npmjs.org/next/-/next-16.0.1.tgz",
- "integrity": "sha512-e9RLSssZwd35p7/vOa+hoDFggUZIUbZhIUSLZuETCwrCVvxOs87NamoUzT+vbcNAL8Ld9GobBnWOA6SbV/arOw==",
+ "version": "16.0.10",
+ "resolved": "https://registry.npmjs.org/next/-/next-16.0.10.tgz",
+ "integrity": "sha512-RtWh5PUgI+vxlV3HdR+IfWA1UUHu0+Ram/JBO4vWB54cVPentCD0e+lxyAYEsDTqGGMg7qpjhKh6dc6aW7W/sA==",
"license": "MIT",
"dependencies": {
- "@next/env": "16.0.1",
+ "@next/env": "16.0.10",
"@swc/helpers": "0.5.15",
"caniuse-lite": "^1.0.30001579",
"postcss": "8.4.31",
@@ -5268,14 +5358,14 @@
"node": ">=20.9.0"
},
"optionalDependencies": {
- "@next/swc-darwin-arm64": "16.0.1",
- "@next/swc-darwin-x64": "16.0.1",
- "@next/swc-linux-arm64-gnu": "16.0.1",
- "@next/swc-linux-arm64-musl": "16.0.1",
- "@next/swc-linux-x64-gnu": "16.0.1",
- "@next/swc-linux-x64-musl": "16.0.1",
- "@next/swc-win32-arm64-msvc": "16.0.1",
- "@next/swc-win32-x64-msvc": "16.0.1",
+ "@next/swc-darwin-arm64": "16.0.10",
+ "@next/swc-darwin-x64": "16.0.10",
+ "@next/swc-linux-arm64-gnu": "16.0.10",
+ "@next/swc-linux-arm64-musl": "16.0.10",
+ "@next/swc-linux-x64-gnu": "16.0.10",
+ "@next/swc-linux-x64-musl": "16.0.10",
+ "@next/swc-win32-arm64-msvc": "16.0.10",
+ "@next/swc-win32-x64-msvc": "16.0.10",
"sharp": "^0.34.4"
},
"peerDependencies": {
@@ -5376,6 +5466,20 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/node-sql-parser": {
+ "version": "5.3.13",
+ "resolved": "https://registry.npmjs.org/node-sql-parser/-/node-sql-parser-5.3.13.tgz",
+ "integrity": "sha512-heyWv3lLjKHpcBDMUSR+R0DohRYZTYq+Ro3hJ4m9Ia8ccdKbL5UijIaWr2L4co+bmmFuvBVZ4v23QW2PqvBFAA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/pegjs": "^0.10.0",
+ "big-integer": "^1.6.48"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/npm-normalize-package-bin": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz",
@@ -5685,6 +5789,44 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/prettier": {
+ "version": "3.7.4",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz",
+ "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-plugin-sql": {
+ "version": "0.19.2",
+ "resolved": "https://registry.npmjs.org/prettier-plugin-sql/-/prettier-plugin-sql-0.19.2.tgz",
+ "integrity": "sha512-DAu1Jcanpvs32OAOXsqaVXOpPs4nFLVkB3XwzRiZZVNL5/c+XdlNxWFMiMpMhYhmCG5BW3srK8mhikCOv5tPfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jsox": "^1.2.123",
+ "node-sql-parser": "^5.3.10",
+ "sql-formatter": "^15.6.5",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ },
+ "peerDependencies": {
+ "prettier": "^3.0.3"
+ }
+ },
"node_modules/proc-log": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.0.0.tgz",
@@ -5738,6 +5880,27 @@
],
"license": "MIT"
},
+ "node_modules/railroad-diagrams": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
+ "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==",
+ "dev": true,
+ "license": "CC0-1.0"
+ },
+ "node_modules/randexp": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz",
+ "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "discontinuous-range": "1.0.0",
+ "ret": "~0.1.10"
+ },
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
"node_modules/react": {
"version": "19.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
@@ -5861,6 +6024,16 @@
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
}
},
+ "node_modules/ret": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
"node_modules/reusify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
@@ -6195,6 +6368,20 @@
"node": ">=0.10.0"
}
},
+ "node_modules/sql-formatter": {
+ "version": "15.6.11",
+ "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.6.11.tgz",
+ "integrity": "sha512-T2aqOqwpGNqDvKNLJqsIVPhEgDCEp795GeXZg7AqbDTHmaEDBBAy/rwBd8lxnlYEjFm/DI+AsD7dnmJNhlUSWw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1",
+ "nearley": "^2.20.1"
+ },
+ "bin": {
+ "sql-formatter": "bin/sql-formatter-cli.cjs"
+ }
+ },
"node_modules/stable-hash": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz",
@@ -6376,9 +6563,9 @@
}
},
"node_modules/supabase": {
- "version": "2.58.5",
- "resolved": "https://registry.npmjs.org/supabase/-/supabase-2.58.5.tgz",
- "integrity": "sha512-mYZSkUIePTdmwlHd26Pff8wpmjfre8gcuWzrc5QqhZgZvCXugVzAQQhcjaQisw5kusbPQWNIjUwcHYEKmejhPw==",
+ "version": "2.61.2",
+ "resolved": "https://registry.npmjs.org/supabase/-/supabase-2.61.2.tgz",
+ "integrity": "sha512-dSmCHErwEQrpSQb1PKzpwZqhEl8qj8KVzVtqJBcKROmPOeWZ9CAghxW5uX2B1bGKPjVXAN6MA4rP/Mr7+qmj1A==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
diff --git a/package.json b/package.json
index 8b899b9..6622171 100644
--- a/package.json
+++ b/package.json
@@ -6,12 +6,14 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
- "lint": "eslint"
+ "lint": "eslint",
+ "format:check": "prettier --check .",
+ "format:fix": "prettier --write ."
},
"dependencies": {
"@supabase/ssr": "^0.7.0",
"@supabase/supabase-js": "^2.81.1",
- "next": "16.0.1",
+ "next": "^16.0.7",
"react": "19.2.0",
"react-dom": "19.2.0"
},
@@ -22,6 +24,9 @@
"@types/react-dom": "^19",
"eslint": "^9",
"eslint-config-next": "16.0.1",
+ "eslint-config-prettier": "^10.1.8",
+ "prettier": "^3.7.4",
+ "prettier-plugin-sql": "^0.19.2",
"supabase": "^2.58.5",
"tailwindcss": "^4",
"typescript": "^5"
diff --git a/supabase/migrations/20251125060428_create_stores_table.sql b/supabase/migrations/20251125060428_create_stores_table.sql
new file mode 100644
index 0000000..33595ec
--- /dev/null
+++ b/supabase/migrations/20251125060428_create_stores_table.sql
@@ -0,0 +1,90 @@
+
+ create table "public"."stores" (
+ "store_id" text,
+ "name" text,
+ "street_address" text
+ );
+
+
+alter table "public"."stores" enable row level security;
+
+grant delete on table "public"."stores" to "anon";
+
+grant insert on table "public"."stores" to "anon";
+
+grant references on table "public"."stores" to "anon";
+
+grant select on table "public"."stores" to "anon";
+
+grant trigger on table "public"."stores" to "anon";
+
+grant truncate on table "public"."stores" to "anon";
+
+grant update on table "public"."stores" to "anon";
+
+grant delete on table "public"."stores" to "authenticated";
+
+grant insert on table "public"."stores" to "authenticated";
+
+grant references on table "public"."stores" to "authenticated";
+
+grant select on table "public"."stores" to "authenticated";
+
+grant trigger on table "public"."stores" to "authenticated";
+
+grant truncate on table "public"."stores" to "authenticated";
+
+grant update on table "public"."stores" to "authenticated";
+
+grant delete on table "public"."stores" to "service_role";
+
+grant insert on table "public"."stores" to "service_role";
+
+grant references on table "public"."stores" to "service_role";
+
+grant select on table "public"."stores" to "service_role";
+
+grant trigger on table "public"."stores" to "service_role";
+
+grant truncate on table "public"."stores" to "service_role";
+
+grant update on table "public"."stores" to "service_role";
+
+
+ create policy "public can delete entries in stores"
+ on "public"."stores"
+ as permissive
+ for delete
+ to anon
+using (true);
+
+
+
+ create policy "public can insert entries in stores"
+ on "public"."stores"
+ as permissive
+ for insert
+ to anon
+with check (true);
+
+
+
+ create policy "public can read entries in stores"
+ on "public"."stores"
+ as permissive
+ for select
+ to anon
+using (true);
+
+
+
+ create policy "public can update entries in stores"
+ on "public"."stores"
+ as permissive
+ for update
+ to anon
+using (true)
+with check (true);
+
+
+
diff --git a/supabase/migrations/20251125063314_create_donations_table.sql b/supabase/migrations/20251125063314_create_donations_table.sql
new file mode 100644
index 0000000..27f39be
--- /dev/null
+++ b/supabase/migrations/20251125063314_create_donations_table.sql
@@ -0,0 +1,106 @@
+
+ create table "public"."donations" (
+ "donation_id" text not null default (gen_random_uuid())::text,
+ "receiver_user_id" text not null,
+ "store_id" text,
+ "date_submitted" timestamp with time zone default CURRENT_TIMESTAMP,
+ "donor_is_individual" boolean not null,
+ "donor_individual_name" text,
+ "donor_business_name" text,
+ "donor_business_contact_name" text,
+ "donor_email" character varying(255),
+ "donor_phone" character varying(20),
+ "donor_street_address" boolean not null,
+ "donor_receive_mailings" boolean not null,
+ "donor_receive_emails" boolean not null,
+ "donor_remain_anonymous" boolean not null,
+ "estimated_value" numeric not null,
+ "items_donated" text not null
+ );
+
+
+alter table "public"."donations" enable row level security;
+
+CREATE UNIQUE INDEX donations_pkey ON public.donations USING btree (donation_id);
+
+alter table "public"."donations" add constraint "donations_pkey" PRIMARY KEY using index "donations_pkey";
+
+grant delete on table "public"."donations" to "anon";
+
+grant insert on table "public"."donations" to "anon";
+
+grant references on table "public"."donations" to "anon";
+
+grant select on table "public"."donations" to "anon";
+
+grant trigger on table "public"."donations" to "anon";
+
+grant truncate on table "public"."donations" to "anon";
+
+grant update on table "public"."donations" to "anon";
+
+grant delete on table "public"."donations" to "authenticated";
+
+grant insert on table "public"."donations" to "authenticated";
+
+grant references on table "public"."donations" to "authenticated";
+
+grant select on table "public"."donations" to "authenticated";
+
+grant trigger on table "public"."donations" to "authenticated";
+
+grant truncate on table "public"."donations" to "authenticated";
+
+grant update on table "public"."donations" to "authenticated";
+
+grant delete on table "public"."donations" to "service_role";
+
+grant insert on table "public"."donations" to "service_role";
+
+grant references on table "public"."donations" to "service_role";
+
+grant select on table "public"."donations" to "service_role";
+
+grant trigger on table "public"."donations" to "service_role";
+
+grant truncate on table "public"."donations" to "service_role";
+
+grant update on table "public"."donations" to "service_role";
+
+
+ create policy "public can delete entries in donations"
+ on "public"."donations"
+ as permissive
+ for delete
+ to anon
+using (true);
+
+
+
+ create policy "public can insert entries in donations"
+ on "public"."donations"
+ as permissive
+ for insert
+ to anon
+with check (true);
+
+
+
+ create policy "public can read entries in donations"
+ on "public"."donations"
+ as permissive
+ for select
+ to anon
+using (true);
+
+
+
+ create policy "public can update entries in donations"
+ on "public"."donations"
+ as permissive
+ for update
+ to anon
+with check (true);
+
+
+
diff --git a/supabase/migrations/20251201081622_create_ticket_items.sql b/supabase/migrations/20251201081622_create_ticket_items.sql
new file mode 100644
index 0000000..16fed36
--- /dev/null
+++ b/supabase/migrations/20251201081622_create_ticket_items.sql
@@ -0,0 +1,93 @@
+
+ create table "public"."ticket_items" (
+ "ticket_item_id" uuid default extensions.uuid_generate_v4(),
+ "ticket_id" uuid not null,
+ "inventory_item_id" uuid,
+ "free_text_description" text,
+ "quantity_requested" integer,
+ "is_in_stock_request" boolean not null
+ );
+
+
+alter table "public"."ticket_items" enable row level security;
+
+grant delete on table "public"."ticket_items" to "anon";
+
+grant insert on table "public"."ticket_items" to "anon";
+
+grant references on table "public"."ticket_items" to "anon";
+
+grant select on table "public"."ticket_items" to "anon";
+
+grant trigger on table "public"."ticket_items" to "anon";
+
+grant truncate on table "public"."ticket_items" to "anon";
+
+grant update on table "public"."ticket_items" to "anon";
+
+grant delete on table "public"."ticket_items" to "authenticated";
+
+grant insert on table "public"."ticket_items" to "authenticated";
+
+grant references on table "public"."ticket_items" to "authenticated";
+
+grant select on table "public"."ticket_items" to "authenticated";
+
+grant trigger on table "public"."ticket_items" to "authenticated";
+
+grant truncate on table "public"."ticket_items" to "authenticated";
+
+grant update on table "public"."ticket_items" to "authenticated";
+
+grant delete on table "public"."ticket_items" to "service_role";
+
+grant insert on table "public"."ticket_items" to "service_role";
+
+grant references on table "public"."ticket_items" to "service_role";
+
+grant select on table "public"."ticket_items" to "service_role";
+
+grant trigger on table "public"."ticket_items" to "service_role";
+
+grant truncate on table "public"."ticket_items" to "service_role";
+
+grant update on table "public"."ticket_items" to "service_role";
+
+
+ create policy "public can delete tiecket_items"
+ on "public"."ticket_items"
+ as permissive
+ for delete
+ to anon
+using (true);
+
+
+
+ create policy "public can insert ticket_items"
+ on "public"."ticket_items"
+ as permissive
+ for insert
+ to anon
+with check (true);
+
+
+
+ create policy "public can read ticket_items"
+ on "public"."ticket_items"
+ as permissive
+ for select
+ to anon
+using (true);
+
+
+
+ create policy "public can update ticket_items"
+ on "public"."ticket_items"
+ as permissive
+ for update
+ to anon
+using (true)
+with check (true);
+
+
+
diff --git a/supabase/migrations/20251202055330_remote_schema.sql b/supabase/migrations/20251202055330_remote_schema.sql
new file mode 100644
index 0000000..375c089
--- /dev/null
+++ b/supabase/migrations/20251202055330_remote_schema.sql
@@ -0,0 +1,57 @@
+drop policy "public can delete entries in donations" on "public"."donations";
+
+drop policy "public can insert entries in donations" on "public"."donations";
+
+drop policy "public can read entries in donations" on "public"."donations";
+
+drop policy "public can update entries in donations" on "public"."donations";
+
+revoke delete on table "public"."donations" from "anon";
+
+revoke insert on table "public"."donations" from "anon";
+
+revoke references on table "public"."donations" from "anon";
+
+revoke select on table "public"."donations" from "anon";
+
+revoke trigger on table "public"."donations" from "anon";
+
+revoke truncate on table "public"."donations" from "anon";
+
+revoke update on table "public"."donations" from "anon";
+
+revoke delete on table "public"."donations" from "authenticated";
+
+revoke insert on table "public"."donations" from "authenticated";
+
+revoke references on table "public"."donations" from "authenticated";
+
+revoke select on table "public"."donations" from "authenticated";
+
+revoke trigger on table "public"."donations" from "authenticated";
+
+revoke truncate on table "public"."donations" from "authenticated";
+
+revoke update on table "public"."donations" from "authenticated";
+
+revoke delete on table "public"."donations" from "service_role";
+
+revoke insert on table "public"."donations" from "service_role";
+
+revoke references on table "public"."donations" from "service_role";
+
+revoke select on table "public"."donations" from "service_role";
+
+revoke trigger on table "public"."donations" from "service_role";
+
+revoke truncate on table "public"."donations" from "service_role";
+
+revoke update on table "public"."donations" from "service_role";
+
+alter table "public"."donations" drop constraint "donations_pkey";
+
+drop index if exists "public"."donations_pkey";
+
+drop table "public"."donations";
+
+
diff --git a/supabase/migrations/20251202064747_fix_donations_type.sql b/supabase/migrations/20251202064747_fix_donations_type.sql
new file mode 100644
index 0000000..31012e3
--- /dev/null
+++ b/supabase/migrations/20251202064747_fix_donations_type.sql
@@ -0,0 +1,106 @@
+
+ create table "public"."donations" (
+ "donation_id" uuid not null default extensions.uuid_generate_v4(),
+ "receiver_user_id" uuid not null,
+ "store_id" uuid,
+ "date_submitted" timestamp with time zone default CURRENT_TIMESTAMP,
+ "donor_is_individual" boolean not null,
+ "donor_individual_name" text,
+ "donor_business_name" text,
+ "donor_business_contact_name" text,
+ "donor_email" character varying(255),
+ "donor_phone" character varying(20),
+ "donor_street_address" text,
+ "donor_receive_mailings" boolean not null,
+ "donor_receive_emails" boolean not null,
+ "donor_remain_anonymous" boolean not null,
+ "estimated_value" numeric not null,
+ "items_donated" text not null
+ );
+
+
+alter table "public"."donations" enable row level security;
+
+CREATE UNIQUE INDEX donations_pkey ON public.donations USING btree (donation_id);
+
+alter table "public"."donations" add constraint "donations_pkey" PRIMARY KEY using index "donations_pkey";
+
+grant delete on table "public"."donations" to "anon";
+
+grant insert on table "public"."donations" to "anon";
+
+grant references on table "public"."donations" to "anon";
+
+grant select on table "public"."donations" to "anon";
+
+grant trigger on table "public"."donations" to "anon";
+
+grant truncate on table "public"."donations" to "anon";
+
+grant update on table "public"."donations" to "anon";
+
+grant delete on table "public"."donations" to "authenticated";
+
+grant insert on table "public"."donations" to "authenticated";
+
+grant references on table "public"."donations" to "authenticated";
+
+grant select on table "public"."donations" to "authenticated";
+
+grant trigger on table "public"."donations" to "authenticated";
+
+grant truncate on table "public"."donations" to "authenticated";
+
+grant update on table "public"."donations" to "authenticated";
+
+grant delete on table "public"."donations" to "service_role";
+
+grant insert on table "public"."donations" to "service_role";
+
+grant references on table "public"."donations" to "service_role";
+
+grant select on table "public"."donations" to "service_role";
+
+grant trigger on table "public"."donations" to "service_role";
+
+grant truncate on table "public"."donations" to "service_role";
+
+grant update on table "public"."donations" to "service_role";
+
+
+ create policy "public can delete entries in donations"
+ on "public"."donations"
+ as permissive
+ for delete
+ to anon
+using (true);
+
+
+
+ create policy "public can insert entries in donations"
+ on "public"."donations"
+ as permissive
+ for insert
+ to anon
+with check (true);
+
+
+
+ create policy "public can read entries in donations"
+ on "public"."donations"
+ as permissive
+ for select
+ to anon
+using (true);
+
+
+
+ create policy "public can update entries in donations"
+ on "public"."donations"
+ as permissive
+ for update
+ to anon
+with check (true);
+
+
+
diff --git a/supabase/migrations/20251205044154_update_stores_table.sql b/supabase/migrations/20251205044154_update_stores_table.sql
new file mode 100644
index 0000000..03082f4
--- /dev/null
+++ b/supabase/migrations/20251205044154_update_stores_table.sql
@@ -0,0 +1,11 @@
+alter table "public"."stores" alter column "store_id" set default extensions.uuid_generate_v4();
+
+alter table "public"."stores" alter column "store_id" set not null;
+
+alter table "public"."stores" alter column "store_id" set data type uuid using "store_id"::uuid;
+
+CREATE UNIQUE INDEX stores_pkey ON public.stores USING btree (store_id);
+
+alter table "public"."stores" add constraint "stores_pkey" PRIMARY KEY using index "stores_pkey";
+
+
diff --git a/supabase/migrations/20251205055058_add_primary_key.sql b/supabase/migrations/20251205055058_add_primary_key.sql
new file mode 100644
index 0000000..0dfa520
--- /dev/null
+++ b/supabase/migrations/20251205055058_add_primary_key.sql
@@ -0,0 +1,7 @@
+alter table "public"."ticket_items" alter column "ticket_item_id" set not null;
+
+CREATE UNIQUE INDEX ticket_items_pkey ON public.ticket_items USING btree (ticket_item_id);
+
+alter table "public"."ticket_items" add constraint "ticket_items_pkey" PRIMARY KEY using index "ticket_items_pkey";
+
+
diff --git a/supabase/migrations/20251205055906_inventory_items.sql b/supabase/migrations/20251205055906_inventory_items.sql
new file mode 100644
index 0000000..ec2e284
--- /dev/null
+++ b/supabase/migrations/20251205055906_inventory_items.sql
@@ -0,0 +1,99 @@
+
+ create table "public"."inventory_items" (
+ "inventory_item_id" uuid not null default extensions.uuid_generate_v4(),
+ "store_id" uuid not null,
+ "subcategory" integer not null,
+ "item" character varying(255) not null,
+ "description" text not null,
+ "photo_url" text,
+ "quantity_available" integer not null,
+ "is_hidden" boolean not null
+ );
+
+
+alter table "public"."inventory_items" enable row level security;
+
+CREATE UNIQUE INDEX inventory_items_pkey ON public.inventory_items USING btree (inventory_item_id);
+
+alter table "public"."inventory_items" add constraint "inventory_items_pkey" PRIMARY KEY using index "inventory_items_pkey";
+
+grant delete on table "public"."inventory_items" to "anon";
+
+grant insert on table "public"."inventory_items" to "anon";
+
+grant references on table "public"."inventory_items" to "anon";
+
+grant select on table "public"."inventory_items" to "anon";
+
+grant trigger on table "public"."inventory_items" to "anon";
+
+grant truncate on table "public"."inventory_items" to "anon";
+
+grant update on table "public"."inventory_items" to "anon";
+
+grant delete on table "public"."inventory_items" to "authenticated";
+
+grant insert on table "public"."inventory_items" to "authenticated";
+
+grant references on table "public"."inventory_items" to "authenticated";
+
+grant select on table "public"."inventory_items" to "authenticated";
+
+grant trigger on table "public"."inventory_items" to "authenticated";
+
+grant truncate on table "public"."inventory_items" to "authenticated";
+
+grant update on table "public"."inventory_items" to "authenticated";
+
+grant delete on table "public"."inventory_items" to "service_role";
+
+grant insert on table "public"."inventory_items" to "service_role";
+
+grant references on table "public"."inventory_items" to "service_role";
+
+grant select on table "public"."inventory_items" to "service_role";
+
+grant trigger on table "public"."inventory_items" to "service_role";
+
+grant truncate on table "public"."inventory_items" to "service_role";
+
+grant update on table "public"."inventory_items" to "service_role";
+
+
+ create policy "public can delete entries in inventory_items"
+ on "public"."inventory_items"
+ as permissive
+ for delete
+ to anon
+using (true);
+
+
+
+ create policy "public can insert entries in inventory_items"
+ on "public"."inventory_items"
+ as permissive
+ for insert
+ to anon
+with check (true);
+
+
+
+ create policy "public can select entries in inventory_items"
+ on "public"."inventory_items"
+ as permissive
+ for select
+ to anon
+using (true);
+
+
+
+ create policy "public can update entries in inventory_items"
+ on "public"."inventory_items"
+ as permissive
+ for update
+ to anon
+using (true)
+with check (true);
+
+
+
diff --git a/supabase/migrations/20251205060123_fix_typo.sql b/supabase/migrations/20251205060123_fix_typo.sql
new file mode 100644
index 0000000..2e4070f
--- /dev/null
+++ b/supabase/migrations/20251205060123_fix_typo.sql
@@ -0,0 +1,12 @@
+drop policy "public can delete tiecket_items" on "public"."ticket_items";
+
+
+ create policy "public can delete ticket_items"
+ on "public"."ticket_items"
+ as permissive
+ for delete
+ to anon
+using (true);
+
+
+
diff --git a/supabase/migrations/20251205063407_add_ticket_status_enum.sql b/supabase/migrations/20251205063407_add_ticket_status_enum.sql
new file mode 100644
index 0000000..3c4ac0b
--- /dev/null
+++ b/supabase/migrations/20251205063407_add_ticket_status_enum.sql
@@ -0,0 +1,98 @@
+create type "public"."ticket_status" as enum ('requested', 'ready', 'rejected', 'fulfilled');
+
+
+ create table "public"."tickets" (
+ "ticket_id" uuid not null default extensions.uuid_generate_v4(),
+ "requestor_user_id" uuid not null,
+ "store_id" uuid not null,
+ "status" public.ticket_status not null,
+ "date_submitted" timestamp with time zone default now()
+ );
+
+
+alter table "public"."tickets" enable row level security;
+
+CREATE UNIQUE INDEX tickets_pkey ON public.tickets USING btree (ticket_id);
+
+alter table "public"."tickets" add constraint "tickets_pkey" PRIMARY KEY using index "tickets_pkey";
+
+grant delete on table "public"."tickets" to "anon";
+
+grant insert on table "public"."tickets" to "anon";
+
+grant references on table "public"."tickets" to "anon";
+
+grant select on table "public"."tickets" to "anon";
+
+grant trigger on table "public"."tickets" to "anon";
+
+grant truncate on table "public"."tickets" to "anon";
+
+grant update on table "public"."tickets" to "anon";
+
+grant delete on table "public"."tickets" to "authenticated";
+
+grant insert on table "public"."tickets" to "authenticated";
+
+grant references on table "public"."tickets" to "authenticated";
+
+grant select on table "public"."tickets" to "authenticated";
+
+grant trigger on table "public"."tickets" to "authenticated";
+
+grant truncate on table "public"."tickets" to "authenticated";
+
+grant update on table "public"."tickets" to "authenticated";
+
+grant delete on table "public"."tickets" to "service_role";
+
+grant insert on table "public"."tickets" to "service_role";
+
+grant references on table "public"."tickets" to "service_role";
+
+grant select on table "public"."tickets" to "service_role";
+
+grant trigger on table "public"."tickets" to "service_role";
+
+grant truncate on table "public"."tickets" to "service_role";
+
+grant update on table "public"."tickets" to "service_role";
+
+
+ create policy "public can delete entries in tickets"
+ on "public"."tickets"
+ as permissive
+ for delete
+ to anon
+using (true);
+
+
+
+ create policy "public can insert entries in tickets"
+ on "public"."tickets"
+ as permissive
+ for insert
+ to anon
+with check (true);
+
+
+
+ create policy "public can read entries in tickets"
+ on "public"."tickets"
+ as permissive
+ for select
+ to anon
+using (true);
+
+
+
+ create policy "public can update entries in tickets"
+ on "public"."tickets"
+ as permissive
+ for update
+ to anon
+using (true)
+with check (true);
+
+
+
diff --git a/supabase/migrations/20251218042006_minor_table_edits.sql b/supabase/migrations/20251218042006_minor_table_edits.sql
new file mode 100644
index 0000000..79aca1f
--- /dev/null
+++ b/supabase/migrations/20251218042006_minor_table_edits.sql
@@ -0,0 +1,11 @@
+alter table "public"."donations" alter column "donor_email" set not null;
+
+alter table "public"."inventory_items" drop column "subcategory";
+
+alter table "public"."inventory_items" add column "subcategory_id" integer not null;
+
+alter table "public"."stores" alter column "name" set not null;
+
+alter table "public"."stores" alter column "street_address" set not null;
+
+
diff --git a/supabase/schemas/donations.sql b/supabase/schemas/donations.sql
new file mode 100644
index 0000000..b3f9916
--- /dev/null
+++ b/supabase/schemas/donations.sql
@@ -0,0 +1,49 @@
+/*
+- Create the donations table according to schema described
+- Write RLS (row level security) policies following supabase/schemas/example.sql
+that enable unauthenticated users to view/update the table
+*/
+create table donations (
+ donation_id uuid default uuid_generate_v4 () primary key, -- generated by default
+ receiver_user_id uuid not null, -- references users(id), -- linked to users table, required
+ store_id uuid, -- references stores(id), -- linked to stores table, optional
+ date_submitted timestamp with time zone default current_timestamp, -- generated by default
+ donor_is_individual boolean not null, -- required, used if donor is an individual
+ donor_individual_name text, -- optional, used if donor is an individual
+ donor_business_name text, -- optional, used if donor is a business
+ donor_business_contact_name text, -- optional, used if donor is a business
+ donor_email varchar(255) not null, -- can't store more than 255 characters
+ donor_phone varchar(20), -- optional, can't store more than 20 characters
+ donor_street_address text, -- optional, street address
+ donor_receive_mailings boolean not null, -- required, whether or not donor wants to receive mailings
+ donor_receive_emails boolean not null, -- required, whether or not donor wants to receive emails
+ donor_remain_anonymous boolean not null, -- required, whether or not donor wants to remain anonymous
+ estimated_value numeric not null, -- required, estimated value of donation in USD
+ items_donated text not null -- required, free-text description of items
+);
+
+-- write RLS policies that enable select, insert, update, and delete across all unauthenticated users
+alter table donations enable row level security;
+
+-- select
+create policy "public can read entries in donations" on public.donations for
+select
+ to anon -- applies to anon role (anonymous/public users)
+ using (true);
+
+-- all rows satisfy condition, all rows are readable
+-- insert
+create policy "public can insert entries in donations" on public.donations for insert to anon -- applies to anon role (anonymous/public users)
+with
+ check (true);
+
+-- for insert/update row validation, only rows where condition evaluates to true can be inserted/updated
+-- update
+create policy "public can update entries in donations" on public.donations
+for update
+ to anon
+with
+ check (true);
+
+-- delete
+create policy "public can delete entries in donations" on public.donations for delete to anon using (true);
diff --git a/supabase/schemas/example.sql b/supabase/schemas/example.sql
index ee8272c..01d7190 100644
--- a/supabase/schemas/example.sql
+++ b/supabase/schemas/example.sql
@@ -1,16 +1,11 @@
-create table "example" (
- "id" integer not null,
- "name" text
-);
+create table "example" ("id" integer not null, "name" text);
alter table example enable row level security;
-create policy "public can read example"
-on public.example
-for select to anon
-using (true);
+create policy "public can read example" on public.example for
+select
+ to anon using (true);
-create policy "public can insert entries in example"
-on public.example
-for insert to anon
-with check (true);
\ No newline at end of file
+create policy "public can insert entries in example" on public.example for insert to anon
+with
+ check (true);
diff --git a/supabase/schemas/inventory_items.sql b/supabase/schemas/inventory_items.sql
new file mode 100644
index 0000000..577a71a
--- /dev/null
+++ b/supabase/schemas/inventory_items.sql
@@ -0,0 +1,28 @@
+create table "inventory_items" (
+ "inventory_item_id" uuid primary key default uuid_generate_v4 (),
+ "store_id" uuid not null,
+ "subcategory_id" int not null,
+ "item" varchar(255) not null,
+ "description" text not null,
+ "photo_url" text,
+ "quantity_available" int not null,
+ "is_hidden" boolean not null
+);
+
+alter table "inventory_items" enable row level security;
+
+create policy "public can select entries in inventory_items" on public.inventory_items for
+select
+ to anon using (true);
+
+create policy "public can insert entries in inventory_items" on public.inventory_items for insert to anon
+with
+ check (true);
+
+create policy "public can update entries in inventory_items" on public.inventory_items
+for update
+ to anon using (true)
+with
+ check (true);
+
+create policy "public can delete entries in inventory_items" on public.inventory_items for delete to anon using (true);
diff --git a/supabase/schemas/stores.sql b/supabase/schemas/stores.sql
new file mode 100644
index 0000000..5dae477
--- /dev/null
+++ b/supabase/schemas/stores.sql
@@ -0,0 +1,23 @@
+create table "stores" (
+ store_id uuid default uuid_generate_v4 () primary key,
+ name text not null,
+ street_address text not null
+);
+
+alter table "stores" enable row level security;
+
+create policy "public can read entries in stores" on public.stores for
+select
+ to anon using (true);
+
+create policy "public can insert entries in stores" on public.stores for insert to anon
+with
+ check (true);
+
+create policy "public can update entries in stores" on public.stores
+for update
+ to anon using (true)
+with
+ check (true);
+
+create policy "public can delete entries in stores" on public.stores for delete to anon using (true);
diff --git a/supabase/schemas/ticket_items.sql b/supabase/schemas/ticket_items.sql
new file mode 100644
index 0000000..2857d30
--- /dev/null
+++ b/supabase/schemas/ticket_items.sql
@@ -0,0 +1,32 @@
+create table ticket_items (
+ ticket_item_id uuid default uuid_generate_v4 () primary key,
+ ticket_id uuid not null,
+ inventory_item_id uuid,
+ free_text_description text,
+ quantity_requested int,
+ is_in_stock_request boolean not null
+ /* CONSTRAINT fk_tickets
+ FOREIGN KEY ticket_id
+ REFERENCES tickets(ticket_id)
+ CONSTRAINT fk_inventory_items
+ FOREIGN KEY inventory_item_id
+ REFERENCES inventory_items(inventory_item_id)*/
+);
+
+alter table "ticket_items" enable row level security;
+
+create policy "public can read ticket_items" on public.ticket_items for
+select
+ to anon using (true);
+
+create policy "public can insert ticket_items" on public.ticket_items for insert to anon
+with
+ check (true);
+
+create policy "public can update ticket_items" on public.ticket_items
+for update
+ to anon using (true)
+with
+ check (true);
+
+create policy "public can delete ticket_items" on public.ticket_items for delete to anon using (true);
diff --git a/supabase/schemas/tickets.sql b/supabase/schemas/tickets.sql
new file mode 100644
index 0000000..7d5f427
--- /dev/null
+++ b/supabase/schemas/tickets.sql
@@ -0,0 +1,29 @@
+create type ticket_status as enum('requested', 'ready', 'rejected', 'fulfilled');
+
+create table "tickets" (
+ "ticket_id" uuid default uuid_generate_v4 () primary key,
+ "requestor_user_id" uuid not null,
+ "store_id" uuid not null,
+ "status" ticket_status not null, -- max 50 character status
+ "date_submitted" timestamp with time zone default now()
+ -- FOREIGN KEY (requestor_user_id) REFERENCES users(user_id),
+ -- FOREIGN KEY (store_id) REFERENCES stores(store_id)
+);
+
+alter table tickets enable row level security;
+
+create policy "public can read entries in tickets" on public.tickets for
+select
+ to anon using (true);
+
+create policy "public can insert entries in tickets" on public.tickets for insert to anon
+with
+ check (true);
+
+create policy "public can update entries in tickets" on public.tickets
+for update
+ to anon using (true)
+with
+ check (true);
+
+create policy "public can delete entries in tickets" on public.tickets for delete to anon using (true);
diff --git a/supabase/seeds/example.sql b/supabase/seeds/example.sql
index 16af5b8..f8b4f51 100644
--- a/supabase/seeds/example.sql
+++ b/supabase/seeds/example.sql
@@ -1,5 +1,5 @@
-insert into example
- (id, name)
+insert into
+ example (id, name)
values
(1, 'alice'),
- (2, 'bob');
\ No newline at end of file
+ (2, 'bob');