diff --git a/app/(app)/comms/comms-client.tsx b/app/(app)/comms/comms-client.tsx index f57d184..c1518aa 100644 --- a/app/(app)/comms/comms-client.tsx +++ b/app/(app)/comms/comms-client.tsx @@ -3,16 +3,20 @@ import { useState, useEffect, useRef } from 'react' import { createClient } from '@/lib/supabase/client' import { Hash, Users2, Send, ChevronLeft } from 'lucide-react' +import type { Tables } from '@/types/database' + +type Channel = Tables<'comms_channels'> +type Message = Tables<'comms_messages'> interface Props { - member: any - space: any - channels: any[] + member: Tables<'space_members'> + space: Tables<'spaces'> + channels: Channel[] } export default function CommsClient({ member, space, channels }: Props) { - const [selectedChannel, setSelectedChannel] = useState(channels[0] || null) - const [messages, setMessages] = useState([]) + const [selectedChannel, setSelectedChannel] = useState(channels[0] || null) + const [messages, setMessages] = useState([]) const [newMessage, setNewMessage] = useState('') const [sending, setSending] = useState(false) const [showChannelList, setShowChannelList] = useState(true) diff --git a/app/(app)/contacts/contacts-client.tsx b/app/(app)/contacts/contacts-client.tsx index a17bd02..d1a30e5 100644 --- a/app/(app)/contacts/contacts-client.tsx +++ b/app/(app)/contacts/contacts-client.tsx @@ -3,19 +3,9 @@ import { useState } from 'react' import { Plus, X, Pencil } from 'lucide-react' import { createContact, updateContact, deleteContact } from '@/lib/actions' +import type { Tables } from '@/types/database' -interface Contact { - id: string - name: string - contact_type: string - email?: string - phone?: string - details?: string - note?: string - group_label?: string - tags?: string[] - code?: string -} +type Contact = Tables<'contacts'> const CATEGORY_COLORS: Record = { vendor: 'text-primary border-primary/30 bg-primary/5', diff --git a/app/(app)/dashboard/page.tsx b/app/(app)/dashboard/page.tsx index f8607c0..765600c 100644 --- a/app/(app)/dashboard/page.tsx +++ b/app/(app)/dashboard/page.tsx @@ -1,6 +1,7 @@ import { createClient } from '@/lib/supabase/server' import Link from 'next/link' import { redirect } from 'next/navigation' +import type { Tables } from '@/types/database' function IcoUsers({ className }: { className?: string }) { return @@ -50,7 +51,7 @@ export default async function DashboardPage() { supabase.from('activity_log').select('*').eq('space_id', spaceId).order('created_at', { ascending: false }).limit(6), ]) - const overdueTasks = (tasks ?? []).filter((t: any) => t.due_date && new Date(t.due_date) < new Date()) + const overdueTasks = (tasks ?? []).filter((t) => t.due_date && new Date(t.due_date) < new Date()) const stats = [ { label: 'Active Members', value: activeMembers ?? 0, Ico: IcoUsers, sub: 'in your space', warn: false }, @@ -91,7 +92,7 @@ export default async function DashboardPage() { All tasks
- {(tasks ?? []).length > 0 ? (tasks ?? []).map((task: any) => { + {(tasks ?? []).length > 0 ? (tasks ?? []).map((task) => { const isOverdue = task.due_date && new Date(task.due_date) < new Date() const isDueToday = task.due_date && new Date(task.due_date).toDateString() === new Date().toDateString() return ( @@ -127,7 +128,7 @@ export default async function DashboardPage() { All projects
- {(projects ?? []).length > 0 ? (projects ?? []).map((project: any) => ( + {(projects ?? []).length > 0 ? (projects ?? []).map((project) => (

{project.title}

@@ -167,7 +168,7 @@ export default async function DashboardPage() {

Recent Activity

- {(activity ?? []).length > 0 ? (activity ?? []).map((item: any) => ( + {(activity ?? []).length > 0 ? (activity ?? []).map((item) => (
diff --git a/app/(app)/import/import-client.tsx b/app/(app)/import/import-client.tsx index 311e18f..c9d3229 100644 --- a/app/(app)/import/import-client.tsx +++ b/app/(app)/import/import-client.tsx @@ -246,13 +246,22 @@ export default function ImportClient({ spaceId, role }: Props) { const last_paid_at = obj.last_paid_at ? new Date(obj.last_paid_at).toISOString() : null const has_card_access = /yes|true|1|y/i.test(obj.has_card_access ?? '') + // Map tier value to valid enum or default to 'basic' + const tierMap: Record = { + plus: 'plus', premium: 'plus', full: 'plus', + basic: 'basic', member: 'basic', standard: 'basic', + associate: 'associate', visitor: 'associate', guest: 'associate', + } + const tier = tierMap[(obj.tier || '').toLowerCase()] || 'basic' + const { error } = await supabase.from('space_members').insert({ space_id: spaceId, + user_id: crypto.randomUUID(), display_name: obj.display_name, email: obj.email, phone: obj.phone || null, handle: obj.handle || null, - tier: obj.tier || 'member', + tier, role: 'member', status: 'current', approved: true, diff --git a/app/(app)/members/members-client.tsx b/app/(app)/members/members-client.tsx index e44ff3c..6c5afb5 100644 --- a/app/(app)/members/members-client.tsx +++ b/app/(app)/members/members-client.tsx @@ -3,24 +3,9 @@ import { useState } from 'react' import { Plus, X, ChevronDown } from 'lucide-react' import { addMember, updateMember, approveMember, removeMember } from '@/lib/actions' +import type { Tables } from '@/types/database' -interface Member { - id: string - display_name: string - email: string - phone?: string - handle?: string - tier: string - role: string - status: string - joined_at?: string - last_paid_at?: string - last_payment_at?: string - payment_status?: string - payment_note?: string - has_card_access?: boolean - approved?: boolean -} +type Member = Tables<'space_members'> interface Props { members: Member[] diff --git a/app/(app)/ops/[id]/kb-entry-editor.tsx b/app/(app)/ops/[id]/kb-entry-editor.tsx index 66713bb..f747ad5 100644 --- a/app/(app)/ops/[id]/kb-entry-editor.tsx +++ b/app/(app)/ops/[id]/kb-entry-editor.tsx @@ -6,10 +6,11 @@ import Link from 'next/link' import { ArrowLeft, Pin, Lock } from 'lucide-react' import { createKbEntry, updateKbEntry } from '@/lib/actions' import { toast } from 'sonner' +import type { Tables } from '@/types/database' interface Props { - entry?: any - member: any + entry?: Tables<'knowledge_base'> + member: Tables<'space_members'> } export default function KbEntryEditor({ entry, member }: Props) { diff --git a/app/(app)/ops/ops-client.tsx b/app/(app)/ops/ops-client.tsx index 9b36f8d..0950494 100644 --- a/app/(app)/ops/ops-client.tsx +++ b/app/(app)/ops/ops-client.tsx @@ -6,39 +6,14 @@ import { Plus, Search, Lock, Pin, Eye, EyeOff, Pencil, Trash2, X, ChevronDown, U import { createKbEntry, updateKbEntry, deleteKbEntry } from '@/lib/actions' import { createClient } from '@/lib/supabase/client' import { toast } from 'sonner' +import type { Tables, TablesInsert } from '@/types/database' -interface KbEntry { - id: string - title: string - content: string - description?: string - area?: string - visibility: string - is_pinned: boolean - tags?: string[] - icon?: string - updated_by_name?: string - updated_at: string - created_at: string -} - -interface AreaLead { - id: string - area_name: string - lead_handle: string - lead_id?: string - description?: string -} - -interface Secret { - id: string - title: string - area?: string - created_at: string -} +type KbEntry = Tables<'knowledge_base'> +type AreaLead = Tables<'area_leads'> +type Secret = Tables<'secrets'> interface Props { - member: any + member: Tables<'space_members'> spaceId: string kbEntries: KbEntry[] areaLeads: AreaLead[] diff --git a/app/(app)/payments/payments-client.tsx b/app/(app)/payments/payments-client.tsx index ac92cc6..fcb65aa 100644 --- a/app/(app)/payments/payments-client.tsx +++ b/app/(app)/payments/payments-client.tsx @@ -4,21 +4,14 @@ import { useState } from 'react' import { X, RefreshCcw } from 'lucide-react' import { toast } from 'sonner' import { logCashPayment, linkPaymentToMember } from '@/lib/actions' +import type { Tables } from '@/types/database' -interface Payment { - id: string - platform: string - amount: number - from_identifier: string - from_note?: string - transaction_date: string - link_status: string - member_id?: string +type Payment = Tables<'payments'> & { space_members?: { display_name: string } | null } -interface Member { id: string; display_name: string; email: string } -interface Integration { platform: string; is_connected: boolean; config?: Record } +type Member = Pick, 'id' | 'display_name' | 'email'> +type Integration = Pick, 'platform' | 'is_connected' | 'config'> interface Props { payments: Payment[] diff --git a/app/(app)/projects/projects-client.tsx b/app/(app)/projects/projects-client.tsx index dd8ef9a..a0cec24 100644 --- a/app/(app)/projects/projects-client.tsx +++ b/app/(app)/projects/projects-client.tsx @@ -3,18 +3,9 @@ import { useState } from 'react' import { Plus, X } from 'lucide-react' import { createProject, updateProjectStatus, deleteProject } from '@/lib/actions' +import type { Tables } from '@/types/database' -interface Project { - id: string - title: string - description?: string - status: string - area?: string - tags?: string[] - progress?: number - due_date?: string - created_at: string -} +type Project = Tables<'projects'> const STATUS_COLS = [ { key: 'backlog', label: 'BACKLOG', color: 'text-muted-foreground', dot: 'bg-muted-foreground' }, diff --git a/app/(app)/settings/settings-client.tsx b/app/(app)/settings/settings-client.tsx index cdfae09..8763415 100644 --- a/app/(app)/settings/settings-client.tsx +++ b/app/(app)/settings/settings-client.tsx @@ -3,25 +3,10 @@ import { useState } from 'react' import { X, Check, Copy, Eye, EyeOff, RotateCcw } from 'lucide-react' import { updateSpaceSettings, saveIntegration, disconnectIntegration, rotateWebhookSecret } from '@/lib/actions' +import type { Tables } from '@/types/database' -interface Space { - id: string - name: string - slug: string - city?: string - invite_code?: string - require_approval?: boolean - public_member_directory?: boolean - webhook_secret?: string -} - -interface Integration { - id: string - platform: string - name?: string - is_connected: boolean - config?: Record -} +type Space = Tables<'spaces'> +type Integration = Tables<'integrations'> interface Props { space: Space diff --git a/app/(app)/tasks/tasks-client.tsx b/app/(app)/tasks/tasks-client.tsx index 2a918bd..828a40e 100644 --- a/app/(app)/tasks/tasks-client.tsx +++ b/app/(app)/tasks/tasks-client.tsx @@ -3,30 +3,13 @@ import { useState, useTransition } from 'react' import { Plus, X, CheckCircle2 } from 'lucide-react' import { createTask, claimTask, completeTask, deleteTask } from '@/lib/actions' +import type { Tables } from '@/types/database' -interface Task { - id: string - title: string - description?: string - type?: string - task_type?: string - status: string - area?: string - recurrence?: string - due_date?: string - claimed_by?: string - claimed_by_name?: string - assigned_to?: string - assigned_to_name?: string - progress?: number - subtask_completed?: number - subtask_total?: number - created_at: string -} +type Task = Tables<'tasks'> interface Props { tasks: Task[] - members: { id: string; display_name: string; user_id: string }[] + members: Pick, 'id' | 'display_name' | 'user_id'>[] currentUserId: string spaceId: string } @@ -57,8 +40,8 @@ export function TasksClient({ tasks: initialTasks, members, currentUserId, space // Chores = chore type OR regular tasks without recurrence (the general open pool) // Mine = tasks claimed/assigned to me // Done = completed - const isDone = (t: any) => t.status === 'done' || t.status === 'completed' - const isOpen = (t: any) => !isDone(t) + const isDone = (t: Task) => t.status === 'done' || t.status === 'completed' + const isOpen = (t: Task) => !isDone(t) const chores = tasks.filter(t => isOpen(t) && (!t.recurrence || t.recurrence === 'none')) const ongoing = tasks.filter(t => t.recurrence && t.recurrence !== 'none' && isOpen(t)) const mine = tasks.filter(t => (t.claimed_by === currentUserId || t.assigned_to === currentUserId) && isOpen(t)) diff --git a/components/app-shell.tsx b/components/app-shell.tsx index 19a23f6..f7f1198 100644 --- a/components/app-shell.tsx +++ b/components/app-shell.tsx @@ -8,6 +8,7 @@ import { LayoutDashboard, ListChecks, FolderKanban, Settings2, MessageSquare, Users, CreditCard, BookUser, Download, LogOut, ChevronDown } from 'lucide-react' +import type { Tables } from '@/types/database' const NAV = [ { @@ -38,8 +39,8 @@ const NAV = [ ] interface Props { - member: any - space: any + member: Tables<'space_members'> + space: Tables<'spaces'> children: React.ReactNode } diff --git a/lib/actions.ts b/lib/actions.ts index fc855d6..362ffa8 100644 --- a/lib/actions.ts +++ b/lib/actions.ts @@ -3,6 +3,8 @@ import { createClient } from '@/lib/supabase/server' import { redirect } from 'next/navigation' import { revalidatePath } from 'next/cache' +import type { SupabaseClient } from '@supabase/supabase-js' +import type { Database } from '@/types/database' // ─── Auth ──────────────────────────────────────────────────────────────────── @@ -26,7 +28,7 @@ export async function getUser() { } // ─── Helper: get current member (any non-inactive status) ──────────────────── -async function getMember(supabase: any, userId: string) { +async function getMember(supabase: SupabaseClient, userId: string) { const { data } = await supabase .from('space_members') .select('space_id, role, display_name') @@ -670,6 +672,7 @@ export async function createSecret(formData: { const { data, error } = await supabase.from('secrets').insert({ space_id: member.space_id, title: formData.title, + label: formData.title, value: formData.value, description: formData.description, area: formData.area, diff --git a/lib/supabase/admin.ts b/lib/supabase/admin.ts index e3c5f8f..29556dd 100644 --- a/lib/supabase/admin.ts +++ b/lib/supabase/admin.ts @@ -1,4 +1,5 @@ import { createClient } from '@supabase/supabase-js' +import type { Database } from '@/types/database' /** * Admin client using the service role key. @@ -6,7 +7,7 @@ import { createClient } from '@supabase/supabase-js' * NEVER expose this client to the browser. */ export function createAdminClient() { - return createClient( + return createClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.SUPABASE_SERVICE_ROLE_KEY!, { diff --git a/lib/supabase/client.ts b/lib/supabase/client.ts index c48a435..ace8e20 100644 --- a/lib/supabase/client.ts +++ b/lib/supabase/client.ts @@ -1,7 +1,8 @@ import { createBrowserClient } from '@supabase/ssr' +import type { Database } from '@/types/database' export function createClient() { - return createBrowserClient( + return createBrowserClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, ) diff --git a/lib/supabase/server.ts b/lib/supabase/server.ts index aa01a96..1e9629c 100644 --- a/lib/supabase/server.ts +++ b/lib/supabase/server.ts @@ -1,5 +1,6 @@ import { createServerClient } from '@supabase/ssr' import { cookies } from 'next/headers' +import type { Database } from '@/types/database' /** * Especially important if using Fluid compute: Don't put this client in a @@ -9,7 +10,7 @@ import { cookies } from 'next/headers' export async function createClient() { const cookieStore = await cookies() - return createServerClient( + return createServerClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, { diff --git a/lib/types.ts b/lib/types.ts index cb60f00..8c8382c 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -1,206 +1,38 @@ -// Enum values match live DB exactly -export type MemberTier = 'plus' | 'basic' | 'associate' -export type MemberRole = 'admin' | 'board' | 'treasurer' | 'member' | 'associate' -export type MemberStatus = 'current' | 'late' | 'inactive' | 'unverified' -export type TaskType = 'chore' | 'task' -export type TaskStatus = 'open' | 'claimed' | 'in_progress' | 'overdue' | 'due_today' | 'completed' | 'done' | 'blocked' -export type TaskRecurrence = 'none' | 'daily' | 'weekly' | 'biweekly' | 'monthly' -export type ProjectStatus = 'backlog' | 'in_progress' | 'review' | 'done' | 'blocked' -export type KBVisibility = 'all_members' | 'board' | 'admin_only' -export type ContactType = 'vendor' | 'supplier' | 'partner' | 'landlord' | 'city' -export type PaymentPlatform = 'paypal' | 'zeffy' | 'venmo' | 'cash' -export type PaymentLinkStatus = 'linked' | 'unlinked' -export type ChannelType = 'general' | 'area' | 'ops' | 'project' -export type AreaLeadStatus = 'active' | 'vacant' | 'handoff' +/** + * Re-export types from the generated database types. + * These types are auto-generated from the Supabase schema. + * + * To regenerate: Use the supabase_generate_typescript_types tool + */ -export interface Space { - id: string - name: string - slug: string - city?: string - invite_code: string - require_approval: boolean - public_member_directory: boolean - webhook_secret?: string - created_at: string - updated_at: string -} +import type { Tables, Enums } from '@/types/database' -export interface SpaceMember { - id: string - space_id: string - user_id: string - display_name: string - handle?: string - email?: string - phone?: string - tier: MemberTier - role: MemberRole - status: MemberStatus - joined_at: string - approved: boolean - has_card_access: boolean - last_payment_at?: string - last_paid_at?: string - payment_status?: string - payment_note?: string -} +// ─── Table Row Types ─────────────────────────────────────────────────────────── +export type Space = Tables<'spaces'> +export type SpaceMember = Tables<'space_members'> +export type Task = Tables<'tasks'> +export type Project = Tables<'projects'> +export type KnowledgeBase = Tables<'knowledge_base'> +export type Secret = Tables<'secrets'> +export type AreaLead = Tables<'area_leads'> +export type Contact = Tables<'contacts'> +export type Payment = Tables<'payments'> +export type CommsChannel = Tables<'comms_channels'> +export type CommsMessage = Tables<'comms_messages'> +export type Integration = Tables<'integrations'> +export type ActivityLog = Tables<'activity_log'> -export interface Task { - id: string - space_id: string - task_type: TaskType - title: string - description?: string - status: TaskStatus - area?: string - assigned_to?: string - assigned_to_name?: string - claimed_by?: string - claimed_by_name?: string - requested_by?: string - requested_by_name?: string - due_date?: string - recurrence: TaskRecurrence - last_done_at?: string - subtask_completed?: number - subtask_total?: number - completed_at?: string - created_at: string - updated_at: string -} - -export interface Project { - id: string - space_id: string - title: string - description?: string - status: ProjectStatus - area?: string - tags?: string[] - assignee_names?: string[] - task_count?: number - tasks_completed?: number - due_date?: string - created_at: string - updated_at: string -} - -export interface KnowledgeBase { - id: string - space_id: string - title: string - content?: string - description?: string - area?: string - tags?: string[] - visibility: KBVisibility - access_level?: string - is_pinned: boolean - pinned?: boolean - icon?: string - updated_by_id?: string - updated_by_name?: string - updated_by?: string - created_at: string - updated_at: string -} - -export interface Secret { - id: string - space_id: string - title: string - description?: string - value: string - area?: string - icon?: string - created_at: string - updated_at: string -} - -export interface AreaLead { - id: string - space_id: string - area_code: string - area_name: string - lead_id?: string - lead_handle?: string - status: AreaLeadStatus - created_at: string - updated_at: string -} - -export interface Contact { - id: string - space_id: string - contact_type: ContactType - code: string - name: string - email?: string - phone?: string - details?: string - tags?: string[] - created_at: string - updated_at: string -} - -export interface Payment { - id: string - space_id: string - platform: PaymentPlatform - amount: number - from_identifier: string - from_note?: string - member_id?: string - member_name?: string - link_status: PaymentLinkStatus - transaction_date: string - created_at: string -} - -export interface CommsChannel { - id: string - space_id: string - name: string - channel_type: ChannelType - icon?: string - area_reference?: string - project_id?: string - member_count?: number - created_at: string -} - -export interface CommsMessage { - id: string - space_id: string - channel_id: string - user_id: string - display_name: string - handle?: string - content: string - created_at: string -} - -export interface Integration { - id: string - space_id: string - platform: string - name: string - description?: string - is_connected: boolean - config?: any - created_at: string - updated_at: string -} - -export interface ActivityLog { - id: string - space_id: string - user_id: string - display_name: string - action: string - entity_type: string - entity_id: string - details?: string - created_at: string -} +// ─── Enum Types ──────────────────────────────────────────────────────────────── +export type MemberTier = Enums<'member_tier'> +export type MemberRole = Enums<'member_role'> +export type MemberStatus = Enums<'member_status'> +export type TaskType = Enums<'task_type'> +export type TaskStatus = Enums<'task_status'> +export type TaskRecurrence = Enums<'recurrence_type'> +export type ProjectStatus = Enums<'project_status'> +export type KBVisibility = Enums<'kb_visibility'> +export type ContactType = Enums<'contact_type'> +export type PaymentPlatform = Enums<'payment_platform'> +export type PaymentLinkStatus = Enums<'payment_link_status'> +export type ChannelType = Enums<'channel_type'> +export type AreaLeadStatus = Enums<'area_lead_status'> diff --git a/types/database.ts b/types/database.ts new file mode 100644 index 0000000..27a1a17 --- /dev/null +++ b/types/database.ts @@ -0,0 +1,1037 @@ +export type Json = + | string + | number + | boolean + | null + | { [key: string]: Json | undefined } + | Json[] + +export type Database = { + // Allows to automatically instantiate createClient with right options + // instead of createClient(URL, KEY) + __InternalSupabase: { + PostgrestVersion: "14.1" + } + public: { + Tables: { + activity_log: { + Row: { + action: string + created_at: string + details: string | null + display_name: string | null + entity_id: string | null + entity_type: string | null + id: string + metadata: Json | null + space_id: string + user_id: string | null + } + Insert: { + action: string + created_at?: string + details?: string | null + display_name?: string | null + entity_id?: string | null + entity_type?: string | null + id?: string + metadata?: Json | null + space_id: string + user_id?: string | null + } + Update: { + action?: string + created_at?: string + details?: string | null + display_name?: string | null + entity_id?: string | null + entity_type?: string | null + id?: string + metadata?: Json | null + space_id?: string + user_id?: string | null + } + Relationships: [ + { + foreignKeyName: "activity_log_space_id_fkey" + columns: ["space_id"] + isOneToOne: false + referencedRelation: "spaces" + referencedColumns: ["id"] + }, + ] + } + area_leads: { + Row: { + area_code: string | null + area_name: string + created_at: string + description: string | null + id: string + lead_handle: string | null + lead_id: string | null + notes: string | null + space_id: string + status: Database["public"]["Enums"]["area_lead_status"] + updated_at: string + } + Insert: { + area_code?: string | null + area_name: string + created_at?: string + description?: string | null + id?: string + lead_handle?: string | null + lead_id?: string | null + notes?: string | null + space_id: string + status?: Database["public"]["Enums"]["area_lead_status"] + updated_at?: string + } + Update: { + area_code?: string | null + area_name?: string + created_at?: string + description?: string | null + id?: string + lead_handle?: string | null + lead_id?: string | null + notes?: string | null + space_id?: string + status?: Database["public"]["Enums"]["area_lead_status"] + updated_at?: string + } + Relationships: [ + { + foreignKeyName: "area_leads_lead_id_fkey" + columns: ["lead_id"] + isOneToOne: false + referencedRelation: "space_members" + referencedColumns: ["id"] + }, + { + foreignKeyName: "area_leads_space_id_fkey" + columns: ["space_id"] + isOneToOne: false + referencedRelation: "spaces" + referencedColumns: ["id"] + }, + ] + } + comms_channels: { + Row: { + area_reference: string | null + channel_type: Database["public"]["Enums"]["channel_type"] + created_at: string + created_by: string | null + description: string | null + icon: string | null + id: string + is_archived: boolean + is_default: boolean + member_count: number + name: string + space_id: string + unread_count: number + updated_at: string + } + Insert: { + area_reference?: string | null + channel_type?: Database["public"]["Enums"]["channel_type"] + created_at?: string + created_by?: string | null + description?: string | null + icon?: string | null + id?: string + is_archived?: boolean + is_default?: boolean + member_count?: number + name: string + space_id: string + unread_count?: number + updated_at?: string + } + Update: { + area_reference?: string | null + channel_type?: Database["public"]["Enums"]["channel_type"] + created_at?: string + created_by?: string | null + description?: string | null + icon?: string | null + id?: string + is_archived?: boolean + is_default?: boolean + member_count?: number + name?: string + space_id?: string + unread_count?: number + updated_at?: string + } + Relationships: [ + { + foreignKeyName: "comms_channels_space_id_fkey" + columns: ["space_id"] + isOneToOne: false + referencedRelation: "spaces" + referencedColumns: ["id"] + }, + ] + } + comms_messages: { + Row: { + channel_id: string + content: string + created_at: string + deleted: boolean + display_name: string | null + edited: boolean + handle: string | null + id: string + reply_to: string | null + space_id: string + updated_at: string + user_id: string + } + Insert: { + channel_id: string + content: string + created_at?: string + deleted?: boolean + display_name?: string | null + edited?: boolean + handle?: string | null + id?: string + reply_to?: string | null + space_id: string + updated_at?: string + user_id: string + } + Update: { + channel_id?: string + content?: string + created_at?: string + deleted?: boolean + display_name?: string | null + edited?: boolean + handle?: string | null + id?: string + reply_to?: string | null + space_id?: string + updated_at?: string + user_id?: string + } + Relationships: [ + { + foreignKeyName: "comms_messages_channel_id_fkey" + columns: ["channel_id"] + isOneToOne: false + referencedRelation: "comms_channels" + referencedColumns: ["id"] + }, + { + foreignKeyName: "comms_messages_reply_to_fkey" + columns: ["reply_to"] + isOneToOne: false + referencedRelation: "comms_messages" + referencedColumns: ["id"] + }, + { + foreignKeyName: "comms_messages_space_id_fkey" + columns: ["space_id"] + isOneToOne: false + referencedRelation: "spaces" + referencedColumns: ["id"] + }, + ] + } + contacts: { + Row: { + address: string | null + code: string | null + contact_type: Database["public"]["Enums"]["contact_type"] + created_at: string + created_by: string | null + details: string | null + email: string | null + group_label: string | null + id: string + name: string + note: string | null + notes: string | null + phone: string | null + space_id: string + tags: string[] | null + updated_at: string + } + Insert: { + address?: string | null + code?: string | null + contact_type?: Database["public"]["Enums"]["contact_type"] + created_at?: string + created_by?: string | null + details?: string | null + email?: string | null + group_label?: string | null + id?: string + name: string + note?: string | null + notes?: string | null + phone?: string | null + space_id: string + tags?: string[] | null + updated_at?: string + } + Update: { + address?: string | null + code?: string | null + contact_type?: Database["public"]["Enums"]["contact_type"] + created_at?: string + created_by?: string | null + details?: string | null + email?: string | null + group_label?: string | null + id?: string + name?: string + note?: string | null + notes?: string | null + phone?: string | null + space_id?: string + tags?: string[] | null + updated_at?: string + } + Relationships: [ + { + foreignKeyName: "contacts_space_id_fkey" + columns: ["space_id"] + isOneToOne: false + referencedRelation: "spaces" + referencedColumns: ["id"] + }, + ] + } + integrations: { + Row: { + config: Json | null + created_at: string + credentials: Json | null + description: string | null + id: string + is_connected: boolean + last_sync_at: string | null + name: string | null + platform: string + settings: Json | null + space_id: string + updated_at: string + } + Insert: { + config?: Json | null + created_at?: string + credentials?: Json | null + description?: string | null + id?: string + is_connected?: boolean + last_sync_at?: string | null + name?: string | null + platform: string + settings?: Json | null + space_id: string + updated_at?: string + } + Update: { + config?: Json | null + created_at?: string + credentials?: Json | null + description?: string | null + id?: string + is_connected?: boolean + last_sync_at?: string | null + name?: string | null + platform?: string + settings?: Json | null + space_id?: string + updated_at?: string + } + Relationships: [ + { + foreignKeyName: "integrations_space_id_fkey" + columns: ["space_id"] + isOneToOne: false + referencedRelation: "spaces" + referencedColumns: ["id"] + }, + ] + } + knowledge_base: { + Row: { + access_level: string | null + area: string | null + category: string | null + content: string | null + created_at: string + created_by: string | null + icon: string | null + id: string + is_pinned: boolean + pinned: boolean + space_id: string + tags: string[] | null + title: string + updated_at: string + updated_by: string | null + updated_by_id: string | null + updated_by_name: string | null + visibility: Database["public"]["Enums"]["kb_visibility"] + } + Insert: { + access_level?: string | null + area?: string | null + category?: string | null + content?: string | null + created_at?: string + created_by?: string | null + icon?: string | null + id?: string + is_pinned?: boolean + pinned?: boolean + space_id: string + tags?: string[] | null + title: string + updated_at?: string + updated_by?: string | null + updated_by_id?: string | null + updated_by_name?: string | null + visibility?: Database["public"]["Enums"]["kb_visibility"] + } + Update: { + access_level?: string | null + area?: string | null + category?: string | null + content?: string | null + created_at?: string + created_by?: string | null + icon?: string | null + id?: string + is_pinned?: boolean + pinned?: boolean + space_id?: string + tags?: string[] | null + title?: string + updated_at?: string + updated_by?: string | null + updated_by_id?: string | null + updated_by_name?: string | null + visibility?: Database["public"]["Enums"]["kb_visibility"] + } + Relationships: [ + { + foreignKeyName: "knowledge_base_space_id_fkey" + columns: ["space_id"] + isOneToOne: false + referencedRelation: "spaces" + referencedColumns: ["id"] + }, + { + foreignKeyName: "knowledge_base_updated_by_id_fkey" + columns: ["updated_by_id"] + isOneToOne: false + referencedRelation: "space_members" + referencedColumns: ["id"] + }, + ] + } + payments: { + Row: { + amount: number + created_at: string + currency: string + description: string | null + external_id: string | null + from_identifier: string | null + from_note: string | null + id: string + link_status: Database["public"]["Enums"]["payment_link_status"] + member_id: string | null + member_name: string | null + payer_email: string | null + payer_name: string | null + payment_date: string | null + platform: Database["public"]["Enums"]["payment_platform"] + raw_data: Json | null + space_id: string + status: Database["public"]["Enums"]["payment_link_status"] + transaction_date: string | null + updated_at: string + } + Insert: { + amount: number + created_at?: string + currency?: string + description?: string | null + external_id?: string | null + from_identifier?: string | null + from_note?: string | null + id?: string + link_status?: Database["public"]["Enums"]["payment_link_status"] + member_id?: string | null + member_name?: string | null + payer_email?: string | null + payer_name?: string | null + payment_date?: string | null + platform: Database["public"]["Enums"]["payment_platform"] + raw_data?: Json | null + space_id: string + status?: Database["public"]["Enums"]["payment_link_status"] + transaction_date?: string | null + updated_at?: string + } + Update: { + amount?: number + created_at?: string + currency?: string + description?: string | null + external_id?: string | null + from_identifier?: string | null + from_note?: string | null + id?: string + link_status?: Database["public"]["Enums"]["payment_link_status"] + member_id?: string | null + member_name?: string | null + payer_email?: string | null + payer_name?: string | null + payment_date?: string | null + platform?: Database["public"]["Enums"]["payment_platform"] + raw_data?: Json | null + space_id?: string + status?: Database["public"]["Enums"]["payment_link_status"] + transaction_date?: string | null + updated_at?: string + } + Relationships: [ + { + foreignKeyName: "payments_member_id_fkey" + columns: ["member_id"] + isOneToOne: false + referencedRelation: "space_members" + referencedColumns: ["id"] + }, + { + foreignKeyName: "payments_space_id_fkey" + columns: ["space_id"] + isOneToOne: false + referencedRelation: "spaces" + referencedColumns: ["id"] + }, + ] + } + projects: { + Row: { + area: string | null + assignee_names: string[] | null + assignees: string | null + category: string | null + created_at: string + created_by: string | null + description: string | null + due_date: string | null + id: string + lead_id: string | null + name: string | null + progress: number + space_id: string + status: Database["public"]["Enums"]["project_status"] + tags: string[] | null + task_count: number + tasks_completed: number + title: string + updated_at: string + } + Insert: { + area?: string | null + assignee_names?: string[] | null + assignees?: string | null + category?: string | null + created_at?: string + created_by?: string | null + description?: string | null + due_date?: string | null + id?: string + lead_id?: string | null + name?: string | null + progress?: number + space_id: string + status?: Database["public"]["Enums"]["project_status"] + tags?: string[] | null + task_count?: number + tasks_completed?: number + title: string + updated_at?: string + } + Update: { + area?: string | null + assignee_names?: string[] | null + assignees?: string | null + category?: string | null + created_at?: string + created_by?: string | null + description?: string | null + due_date?: string | null + id?: string + lead_id?: string | null + name?: string | null + progress?: number + space_id?: string + status?: Database["public"]["Enums"]["project_status"] + tags?: string[] | null + task_count?: number + tasks_completed?: number + title?: string + updated_at?: string + } + Relationships: [ + { + foreignKeyName: "projects_space_id_fkey" + columns: ["space_id"] + isOneToOne: false + referencedRelation: "spaces" + referencedColumns: ["id"] + }, + ] + } + secrets: { + Row: { + area: string | null + category: string | null + created_at: string + created_by: string | null + description: string | null + icon: string | null + id: string + label: string + notes: string | null + space_id: string + title: string | null + updated_at: string + value: string + } + Insert: { + area?: string | null + category?: string | null + created_at?: string + created_by?: string | null + description?: string | null + icon?: string | null + id?: string + label: string + notes?: string | null + space_id: string + title?: string | null + updated_at?: string + value: string + } + Update: { + area?: string | null + category?: string | null + created_at?: string + created_by?: string | null + description?: string | null + icon?: string | null + id?: string + label?: string + notes?: string | null + space_id?: string + title?: string | null + updated_at?: string + value?: string + } + Relationships: [ + { + foreignKeyName: "secrets_space_id_fkey" + columns: ["space_id"] + isOneToOne: false + referencedRelation: "spaces" + referencedColumns: ["id"] + }, + ] + } + space_members: { + Row: { + approved: boolean + avatar_url: string | null + bio: string | null + created_at: string + display_name: string | null + dues_paid_until: string | null + email: string | null + handle: string | null + has_card_access: boolean + id: string + joined_at: string | null + last_paid_at: string | null + last_payment_at: string | null + payment_note: string | null + payment_status: string | null + phone: string | null + role: Database["public"]["Enums"]["member_role"] + space_id: string + status: Database["public"]["Enums"]["member_status"] + stripe_customer_id: string | null + tier: Database["public"]["Enums"]["member_tier"] + updated_at: string + user_id: string + } + Insert: { + approved?: boolean + avatar_url?: string | null + bio?: string | null + created_at?: string + display_name?: string | null + dues_paid_until?: string | null + email?: string | null + handle?: string | null + has_card_access?: boolean + id?: string + joined_at?: string | null + last_paid_at?: string | null + last_payment_at?: string | null + payment_note?: string | null + payment_status?: string | null + phone?: string | null + role?: Database["public"]["Enums"]["member_role"] + space_id: string + status?: Database["public"]["Enums"]["member_status"] + stripe_customer_id?: string | null + tier?: Database["public"]["Enums"]["member_tier"] + updated_at?: string + user_id: string + } + Update: { + approved?: boolean + avatar_url?: string | null + bio?: string | null + created_at?: string + display_name?: string | null + dues_paid_until?: string | null + email?: string | null + handle?: string | null + has_card_access?: boolean + id?: string + joined_at?: string | null + last_paid_at?: string | null + last_payment_at?: string | null + payment_note?: string | null + payment_status?: string | null + phone?: string | null + role?: Database["public"]["Enums"]["member_role"] + space_id?: string + status?: Database["public"]["Enums"]["member_status"] + stripe_customer_id?: string | null + tier?: Database["public"]["Enums"]["member_tier"] + updated_at?: string + user_id?: string + } + Relationships: [ + { + foreignKeyName: "space_members_space_id_fkey" + columns: ["space_id"] + isOneToOne: false + referencedRelation: "spaces" + referencedColumns: ["id"] + }, + ] + } + spaces: { + Row: { + address: string | null + city: string | null + created_at: string + description: string | null + id: string + invite_code: string | null + logo_url: string | null + name: string + public_member_directory: boolean | null + require_approval: boolean | null + settings: Json | null + slug: string + timezone: string | null + updated_at: string + webhook_secret: string | null + } + Insert: { + address?: string | null + city?: string | null + created_at?: string + description?: string | null + id?: string + invite_code?: string | null + logo_url?: string | null + name: string + public_member_directory?: boolean | null + require_approval?: boolean | null + settings?: Json | null + slug: string + timezone?: string | null + updated_at?: string + webhook_secret?: string | null + } + Update: { + address?: string | null + city?: string | null + created_at?: string + description?: string | null + id?: string + invite_code?: string | null + logo_url?: string | null + name?: string + public_member_directory?: boolean | null + require_approval?: boolean | null + settings?: Json | null + slug?: string + timezone?: string | null + updated_at?: string + webhook_secret?: string | null + } + Relationships: [] + } + tasks: { + Row: { + area: string | null + assigned_to: string | null + assigned_to_name: string | null + claimed_by: string | null + claimed_by_name: string | null + completed_at: string | null + created_at: string + created_by: string | null + description: string | null + due_date: string | null + id: string + last_done_at: string | null + priority: string | null + progress: number + project_id: string | null + recurrence: Database["public"]["Enums"]["recurrence_type"] | null + requested_by: string | null + requested_by_name: string | null + space_id: string + status: Database["public"]["Enums"]["task_status"] + subtask_completed: number + subtask_total: number + tags: string[] | null + task_type: Database["public"]["Enums"]["task_type"] + title: string + updated_at: string + } + Insert: { + area?: string | null + assigned_to?: string | null + assigned_to_name?: string | null + claimed_by?: string | null + claimed_by_name?: string | null + completed_at?: string | null + created_at?: string + created_by?: string | null + description?: string | null + due_date?: string | null + id?: string + last_done_at?: string | null + priority?: string | null + progress?: number + project_id?: string | null + recurrence?: Database["public"]["Enums"]["recurrence_type"] | null + requested_by?: string | null + requested_by_name?: string | null + space_id: string + status?: Database["public"]["Enums"]["task_status"] + subtask_completed?: number + subtask_total?: number + tags?: string[] | null + task_type?: Database["public"]["Enums"]["task_type"] + title: string + updated_at?: string + } + Update: { + area?: string | null + assigned_to?: string | null + assigned_to_name?: string | null + claimed_by?: string | null + claimed_by_name?: string | null + completed_at?: string | null + created_at?: string + created_by?: string | null + description?: string | null + due_date?: string | null + id?: string + last_done_at?: string | null + priority?: string | null + progress?: number + project_id?: string | null + recurrence?: Database["public"]["Enums"]["recurrence_type"] | null + requested_by?: string | null + requested_by_name?: string | null + space_id?: string + status?: Database["public"]["Enums"]["task_status"] + subtask_completed?: number + subtask_total?: number + tags?: string[] | null + task_type?: Database["public"]["Enums"]["task_type"] + title?: string + updated_at?: string + } + Relationships: [ + { + foreignKeyName: "tasks_project_id_fkey" + columns: ["project_id"] + isOneToOne: false + referencedRelation: "projects" + referencedColumns: ["id"] + }, + { + foreignKeyName: "tasks_space_id_fkey" + columns: ["space_id"] + isOneToOne: false + referencedRelation: "spaces" + referencedColumns: ["id"] + }, + ] + } + } + Views: { + [_ in never]: never + } + Functions: { + get_user_space_ids: { Args: { uid: string }; Returns: string[] } + user_has_role_in_space: { + Args: { allowed_roles: string[]; sid: string; uid: string } + Returns: boolean + } + } + Enums: { + area_lead_status: "active" | "vacant" | "handoff" + channel_type: "general" | "area" | "ops" | "project" + contact_type: "vendor" | "supplier" | "partner" | "landlord" | "city" + kb_visibility: "all_members" | "board" | "admin_only" + member_role: "admin" | "board" | "treasurer" | "member" | "associate" + member_status: "current" | "late" | "inactive" | "unverified" + member_tier: "plus" | "basic" | "associate" + payment_link_status: "linked" | "unlinked" + payment_platform: "paypal" | "zeffy" | "venmo" | "cash" + project_status: "backlog" | "in_progress" | "review" | "done" | "blocked" + recurrence_type: "daily" | "weekly" | "biweekly" | "monthly" | "none" + task_status: + | "open" + | "claimed" + | "in_progress" + | "overdue" + | "due_today" + | "completed" + | "done" + | "blocked" + task_type: "chore" | "task" + } + CompositeTypes: { + [_ in never]: never + } + } +} + +type DatabaseWithoutInternals = Omit + +type DefaultSchema = DatabaseWithoutInternals[Extract] + +export type Tables< + DefaultSchemaTableNameOrOptions extends + | keyof (DefaultSchema["Tables"] & DefaultSchema["Views"]) + | { schema: keyof DatabaseWithoutInternals }, + TableName extends DefaultSchemaTableNameOrOptions extends { + schema: keyof DatabaseWithoutInternals + } + ? keyof (DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] & + DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Views"]) + : never = never, +> = DefaultSchemaTableNameOrOptions extends { + schema: keyof DatabaseWithoutInternals +} + ? (DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] & + DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Views"])[TableName] extends { + Row: infer R + } + ? R + : never + : DefaultSchemaTableNameOrOptions extends keyof (DefaultSchema["Tables"] & + DefaultSchema["Views"]) + ? (DefaultSchema["Tables"] & + DefaultSchema["Views"])[DefaultSchemaTableNameOrOptions] extends { + Row: infer R + } + ? R + : never + : never + +export type TablesInsert< + DefaultSchemaTableNameOrOptions extends + | keyof DefaultSchema["Tables"] + | { schema: keyof DatabaseWithoutInternals }, + TableName extends DefaultSchemaTableNameOrOptions extends { + schema: keyof DatabaseWithoutInternals + } + ? keyof DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] + : never = never, +> = DefaultSchemaTableNameOrOptions extends { + schema: keyof DatabaseWithoutInternals +} + ? DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"][TableName] extends { + Insert: infer I + } + ? I + : never + : DefaultSchemaTableNameOrOptions extends keyof DefaultSchema["Tables"] + ? DefaultSchema["Tables"][DefaultSchemaTableNameOrOptions] extends { + Insert: infer I + } + ? I + : never + : never + +export type TablesUpdate< + DefaultSchemaTableNameOrOptions extends + | keyof DefaultSchema["Tables"] + | { schema: keyof DatabaseWithoutInternals }, + TableName extends DefaultSchemaTableNameOrOptions extends { + schema: keyof DatabaseWithoutInternals + } + ? keyof DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] + : never = never, +> = DefaultSchemaTableNameOrOptions extends { + schema: keyof DatabaseWithoutInternals +} + ? DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"][TableName] extends { + Update: infer U + } + ? U + : never + : DefaultSchemaTableNameOrOptions extends keyof DefaultSchema["Tables"] + ? DefaultSchema["Tables"][DefaultSchemaTableNameOrOptions] extends { + Update: infer U + } + ? U + : never + : never + +export type Enums< + DefaultSchemaEnumNameOrOptions extends + | keyof DefaultSchema["Enums"] + | { schema: keyof DatabaseWithoutInternals }, + EnumName extends DefaultSchemaEnumNameOrOptions extends { + schema: keyof DatabaseWithoutInternals + } + ? keyof DatabaseWithoutInternals[DefaultSchemaEnumNameOrOptions["schema"]]["Enums"] + : never = never, +> = DefaultSchemaEnumNameOrOptions extends { + schema: keyof DatabaseWithoutInternals +} + ? DatabaseWithoutInternals[DefaultSchemaEnumNameOrOptions["schema"]]["Enums"][EnumName] + : DefaultSchemaEnumNameOrOptions extends keyof DefaultSchema["Enums"] + ? DefaultSchema["Enums"][DefaultSchemaEnumNameOrOptions] + : never