diff --git a/apps/api/src/__tests__/routes/tablo.test.ts b/apps/api/src/__tests__/routes/tablo.test.ts index 79fe535..639c24d 100644 --- a/apps/api/src/__tests__/routes/tablo.test.ts +++ b/apps/api/src/__tests__/routes/tablo.test.ts @@ -525,7 +525,9 @@ describe("Tablo Endpoint", () => { expect(latestNotification?.action_type).toBe("created"); // Message is now a JSONB object with en/fr keys expect(latestNotification?.message).toBeDefined(); + // biome-ignore lint/suspicious/noExplicitAny: testClient requires any for dynamic route access expect((latestNotification?.message as any)?.en).toContain("invited"); + // biome-ignore lint/suspicious/noExplicitAny: testClient requires any for dynamic route access expect((latestNotification?.message as any)?.fr).toContain("invité"); expect(latestNotification?.read_at).toBeNull(); }); @@ -570,7 +572,9 @@ describe("Tablo Endpoint", () => { // Should create notification for the newly created temporary user expect(notificationsForInvite?.length || 0).toBeGreaterThan(0); // Message is now a JSONB object with en/fr keys + // biome-ignore lint/suspicious/noExplicitAny: testClient requires any for dynamic route access expect((notificationsForInvite?.[0].message as any)?.en).toContain("invited"); + // biome-ignore lint/suspicious/noExplicitAny: testClient requires any for dynamic route access expect((notificationsForInvite?.[0].message as any)?.fr).toContain("invité"); }); }); diff --git a/apps/api/src/index.ts b/apps/api/src/index.ts index 8d725e4..261a010 100644 --- a/apps/api/src/index.ts +++ b/apps/api/src/index.ts @@ -8,7 +8,6 @@ import { fileURLToPath } from "url"; import { createConfig } from "./config.js"; import { MiddlewareManager } from "./middlewares/middleware.js"; import { getMainRouter } from "./routers/index.js"; -import { getPublicRouter } from "./routers/public.js"; import { loadSecrets, type Secrets } from "./secrets.js"; tracer.init({ @@ -55,7 +54,6 @@ async function startServer(secrets: Secrets) { }); app.route("/api/v1", getMainRouter(config)); - app.route("/api/public", getPublicRouter()); serve( { diff --git a/apps/api/src/routers/index.ts b/apps/api/src/routers/index.ts index 9e84cc3..ab4d2a8 100644 --- a/apps/api/src/routers/index.ts +++ b/apps/api/src/routers/index.ts @@ -16,9 +16,6 @@ export const getMainRouter = (config: AppConfig) => { // Apply supabase middleware globally (needed by all routes) mainRouter.use(middlewareManager.supabase); - // public routes (only need supabase, no other middlewares) - mainRouter.route("/public", getPublicRouter()); - // Apply remaining middlewares after public routes mainRouter.use(middlewareManager.streamChat); mainRouter.use(middlewareManager.r2); @@ -26,6 +23,9 @@ export const getMainRouter = (config: AppConfig) => { mainRouter.use(middlewareManager.stripe); mainRouter.use(middlewareManager.stripeSync); + // public routes + mainRouter.route("/public", getPublicRouter()); + // tasks routes mainRouter.route("/tasks", getTaskRouter()); diff --git a/apps/api/src/routers/public.ts b/apps/api/src/routers/public.ts index b34d16e..15af76d 100644 --- a/apps/api/src/routers/public.ts +++ b/apps/api/src/routers/public.ts @@ -12,6 +12,8 @@ import { } from "../helpers/slots.js"; import type { BaseEnv } from "../types/app.types.js"; +// import { MiddlewareManager } from "../middlewares/middleware.js"; + const factory = createFactory(); const getPublicSlots = factory.createHandlers(async (c) => { @@ -124,7 +126,8 @@ const getPublicSlots = factory.createHandlers(async (c) => { }); export const getPublicRouter = () => { - const publicRouter = new Hono(); + const publicRouter = new Hono(); + publicRouter.get("/slots/:shortUserId/:standardName", ...getPublicSlots); return publicRouter; diff --git a/apps/main/src/components/NotificationPanel.tsx b/apps/main/src/components/NotificationPanel.tsx index f3e24f8..a73ff9d 100644 --- a/apps/main/src/components/NotificationPanel.tsx +++ b/apps/main/src/components/NotificationPanel.tsx @@ -1,3 +1,4 @@ +import type { Database } from "@xtablo/shared-types"; import { Badge } from "@xtablo/ui/components/badge"; import { Button } from "@xtablo/ui/components/button"; import { @@ -13,21 +14,20 @@ import { } from "@xtablo/ui/components/typography"; import { BellIcon, - CheckCheckIcon, CalendarIcon, + CheckCheckIcon, FileTextIcon, KanbanIcon, LayoutDashboardIcon, - UserPlusIcon, MailIcon, + UserPlusIcon, XIcon, } from "lucide-react"; import { useEffect } from "react"; import { useTranslation } from "react-i18next"; import { Link } from "react-router-dom"; -import { useNotifications, useNotificationsSubscription } from "../hooks/notifications"; -import type { Database } from "@xtablo/shared-types"; import { twMerge } from "tailwind-merge"; +import { useNotifications, useNotificationsSubscription } from "../hooks/notifications"; type Notification = Database["public"]["Tables"]["notifications"]["Row"]; diff --git a/apps/main/src/hooks/notifications.ts b/apps/main/src/hooks/notifications.ts index 2d5c4ab..2f136f9 100644 --- a/apps/main/src/hooks/notifications.ts +++ b/apps/main/src/hooks/notifications.ts @@ -1,6 +1,6 @@ -import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; -import { supabase } from "../lib/supabase"; +import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import type { Database } from "@xtablo/shared-types"; +import { supabase } from "../lib/supabase"; type Notification = Database["public"]["Tables"]["notifications"]["Row"]; @@ -8,7 +8,12 @@ export function useNotifications() { const queryClient = useQueryClient(); // Fetch unread notifications - const { data: notifications = [], isLoading, error, refetch } = useQuery({ + const { + data: notifications = [], + isLoading, + error, + refetch, + } = useQuery({ queryKey: ["notifications", "unread"], queryFn: async () => { const { data, error } = await supabase @@ -67,7 +72,11 @@ export function useNotifications() { // Hook to fetch all notifications (including read ones) export function useAllNotifications(limit = 50) { - const { data: notifications = [], isLoading, error } = useQuery({ + const { + data: notifications = [], + isLoading, + error, + } = useQuery({ queryKey: ["notifications", "all", limit], queryFn: async () => { const { data, error } = await supabase @@ -116,4 +125,3 @@ export function useNotificationsSubscription() { return { setupSubscription }; } - diff --git a/packages/shared-types/src/database.types.ts b/packages/shared-types/src/database.types.ts index 0185db5..7a53e32 100644 --- a/packages/shared-types/src/database.types.ts +++ b/packages/shared-types/src/database.types.ts @@ -1,992 +1,1020 @@ -export type Json = - | string - | number - | boolean - | null - | { [key: string]: Json | undefined } - | Json[] +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: "13.0.4" - } + PostgrestVersion: "13.0.4"; + }; public: { Tables: { availabilities: { Row: { - availability_data: Json - created_at: string - exceptions: Json | null - id: number - updated_at: string - user_id: string - } + availability_data: Json; + created_at: string; + exceptions: Json | null; + id: number; + updated_at: string; + user_id: string; + }; Insert: { - availability_data?: Json - created_at?: string - exceptions?: Json | null - id?: number - updated_at?: string - user_id: string - } + availability_data?: Json; + created_at?: string; + exceptions?: Json | null; + id?: number; + updated_at?: string; + user_id: string; + }; Update: { - availability_data?: Json - created_at?: string - exceptions?: Json | null - id?: number - updated_at?: string - user_id?: string - } - Relationships: [] - } + availability_data?: Json; + created_at?: string; + exceptions?: Json | null; + id?: number; + updated_at?: string; + user_id?: string; + }; + Relationships: []; + }; calendar_subscriptions: { Row: { - created_at: string | null - id: string - tablo_id: string - token: string - } + created_at: string | null; + id: string; + tablo_id: string; + token: string; + }; Insert: { - created_at?: string | null - id?: string - tablo_id: string - token: string - } + created_at?: string | null; + id?: string; + tablo_id: string; + token: string; + }; Update: { - created_at?: string | null - id?: string - tablo_id?: string - token?: string - } + created_at?: string | null; + id?: string; + tablo_id?: string; + token?: string; + }; Relationships: [ { - foreignKeyName: "calendar_subscriptions_tablo_id_fkey" - columns: ["tablo_id"] - isOneToOne: true - referencedRelation: "events_and_tablos" - referencedColumns: ["tablo_id"] + foreignKeyName: "calendar_subscriptions_tablo_id_fkey"; + columns: ["tablo_id"]; + isOneToOne: true; + referencedRelation: "events_and_tablos"; + referencedColumns: ["tablo_id"]; }, { - foreignKeyName: "calendar_subscriptions_tablo_id_fkey" - columns: ["tablo_id"] - isOneToOne: true - referencedRelation: "tablos" - referencedColumns: ["id"] + foreignKeyName: "calendar_subscriptions_tablo_id_fkey"; + columns: ["tablo_id"]; + isOneToOne: true; + referencedRelation: "tablos"; + referencedColumns: ["id"]; }, { - foreignKeyName: "calendar_subscriptions_tablo_id_fkey" - columns: ["tablo_id"] - isOneToOne: true - referencedRelation: "user_tablos" - referencedColumns: ["id"] + foreignKeyName: "calendar_subscriptions_tablo_id_fkey"; + columns: ["tablo_id"]; + isOneToOne: true; + referencedRelation: "user_tablos"; + referencedColumns: ["id"]; }, - ] - } + ]; + }; devis: { Row: { - client_email: string - created_at: string - date: string - due_date: string - id: string - items: Json - notes: string | null - number: string - status: Database["public"]["Enums"]["devis_status"] - subtotal: number - tax: number - terms: string | null - total: number - updated_at: string - user_id: string - } + client_email: string; + created_at: string; + date: string; + due_date: string; + id: string; + items: Json; + notes: string | null; + number: string; + status: Database["public"]["Enums"]["devis_status"]; + subtotal: number; + tax: number; + terms: string | null; + total: number; + updated_at: string; + user_id: string; + }; Insert: { - client_email: string - created_at?: string - date: string - due_date: string - id?: string - items?: Json - notes?: string | null - number: string - status?: Database["public"]["Enums"]["devis_status"] - subtotal: number - tax: number - terms?: string | null - total: number - updated_at?: string - user_id: string - } + client_email: string; + created_at?: string; + date: string; + due_date: string; + id?: string; + items?: Json; + notes?: string | null; + number: string; + status?: Database["public"]["Enums"]["devis_status"]; + subtotal: number; + tax: number; + terms?: string | null; + total: number; + updated_at?: string; + user_id: string; + }; Update: { - client_email?: string - created_at?: string - date?: string - due_date?: string - id?: string - items?: Json - notes?: string | null - number?: string - status?: Database["public"]["Enums"]["devis_status"] - subtotal?: number - tax?: number - terms?: string | null - total?: number - updated_at?: string - user_id?: string - } - Relationships: [] - } + client_email?: string; + created_at?: string; + date?: string; + due_date?: string; + id?: string; + items?: Json; + notes?: string | null; + number?: string; + status?: Database["public"]["Enums"]["devis_status"]; + subtotal?: number; + tax?: number; + terms?: string | null; + total?: number; + updated_at?: string; + user_id?: string; + }; + Relationships: []; + }; event_types: { Row: { - config: Json - created_at: string | null - deleted_at: string | null - id: string - is_active: boolean - standard_name: string | null - updated_at: string | null - user_id: string - } + config: Json; + created_at: string | null; + deleted_at: string | null; + id: string; + is_active: boolean; + standard_name: string | null; + updated_at: string | null; + user_id: string; + }; Insert: { - config?: Json - created_at?: string | null - deleted_at?: string | null - id?: string - is_active?: boolean - standard_name?: string | null - updated_at?: string | null - user_id: string - } + config?: Json; + created_at?: string | null; + deleted_at?: string | null; + id?: string; + is_active?: boolean; + standard_name?: string | null; + updated_at?: string | null; + user_id: string; + }; Update: { - config?: Json - created_at?: string | null - deleted_at?: string | null - id?: string - is_active?: boolean - standard_name?: string | null - updated_at?: string | null - user_id?: string - } - Relationships: [] - } + config?: Json; + created_at?: string | null; + deleted_at?: string | null; + id?: string; + is_active?: boolean; + standard_name?: string | null; + updated_at?: string | null; + user_id?: string; + }; + Relationships: []; + }; events: { Row: { - created_at: string | null - created_by: string - deleted_at: string | null - description: string | null - end_time: string | null - id: string - start_date: string - start_time: string - tablo_id: string - title: string - } + created_at: string | null; + created_by: string; + deleted_at: string | null; + description: string | null; + end_time: string | null; + id: string; + start_date: string; + start_time: string; + tablo_id: string; + title: string; + }; Insert: { - created_at?: string | null - created_by: string - deleted_at?: string | null - description?: string | null - end_time?: string | null - id?: string - start_date: string - start_time: string - tablo_id: string - title: string - } + created_at?: string | null; + created_by: string; + deleted_at?: string | null; + description?: string | null; + end_time?: string | null; + id?: string; + start_date: string; + start_time: string; + tablo_id: string; + title: string; + }; Update: { - created_at?: string | null - created_by?: string - deleted_at?: string | null - description?: string | null - end_time?: string | null - id?: string - start_date?: string - start_time?: string - tablo_id?: string - title?: string - } + created_at?: string | null; + created_by?: string; + deleted_at?: string | null; + description?: string | null; + end_time?: string | null; + id?: string; + start_date?: string; + start_time?: string; + tablo_id?: string; + title?: string; + }; Relationships: [ { - foreignKeyName: "fk_events_tablo_id" - columns: ["tablo_id"] - isOneToOne: false - referencedRelation: "events_and_tablos" - referencedColumns: ["tablo_id"] + foreignKeyName: "fk_events_tablo_id"; + columns: ["tablo_id"]; + isOneToOne: false; + referencedRelation: "events_and_tablos"; + referencedColumns: ["tablo_id"]; }, { - foreignKeyName: "fk_events_tablo_id" - columns: ["tablo_id"] - isOneToOne: false - referencedRelation: "tablos" - referencedColumns: ["id"] + foreignKeyName: "fk_events_tablo_id"; + columns: ["tablo_id"]; + isOneToOne: false; + referencedRelation: "tablos"; + referencedColumns: ["id"]; }, { - foreignKeyName: "fk_events_tablo_id" - columns: ["tablo_id"] - isOneToOne: false - referencedRelation: "user_tablos" - referencedColumns: ["id"] + foreignKeyName: "fk_events_tablo_id"; + columns: ["tablo_id"]; + isOneToOne: false; + referencedRelation: "user_tablos"; + referencedColumns: ["id"]; }, - ] - } + ]; + }; feedbacks: { Row: { - created_at: string | null - fd_type: string - id: number - message: string - user_id: string - } + created_at: string | null; + fd_type: string; + id: number; + message: string; + user_id: string; + }; Insert: { - created_at?: string | null - fd_type: string - id?: number - message: string - user_id: string - } + created_at?: string | null; + fd_type: string; + id?: number; + message: string; + user_id: string; + }; Update: { - created_at?: string | null - fd_type?: string - id?: number - message?: string - user_id?: string - } - Relationships: [] - } + created_at?: string | null; + fd_type?: string; + id?: number; + message?: string; + user_id?: string; + }; + Relationships: []; + }; note_access: { Row: { - created_at: string | null - id: number - is_active: boolean | null - note_id: string - tablo_id: string | null - updated_at: string | null - user_id: string - } + created_at: string | null; + id: number; + is_active: boolean | null; + note_id: string; + tablo_id: string | null; + updated_at: string | null; + user_id: string; + }; Insert: { - created_at?: string | null - id?: number - is_active?: boolean | null - note_id: string - tablo_id?: string | null - updated_at?: string | null - user_id: string - } + created_at?: string | null; + id?: number; + is_active?: boolean | null; + note_id: string; + tablo_id?: string | null; + updated_at?: string | null; + user_id: string; + }; Update: { - created_at?: string | null - id?: number - is_active?: boolean | null - note_id?: string - tablo_id?: string | null - updated_at?: string | null - user_id?: string - } + created_at?: string | null; + id?: number; + is_active?: boolean | null; + note_id?: string; + tablo_id?: string | null; + updated_at?: string | null; + user_id?: string; + }; Relationships: [ { - foreignKeyName: "fk_note_access_note_id" - columns: ["note_id"] - isOneToOne: false - referencedRelation: "notes" - referencedColumns: ["id"] + foreignKeyName: "fk_note_access_note_id"; + columns: ["note_id"]; + isOneToOne: false; + referencedRelation: "notes"; + referencedColumns: ["id"]; }, { - foreignKeyName: "fk_note_access_tablo_id" - columns: ["tablo_id"] - isOneToOne: false - referencedRelation: "events_and_tablos" - referencedColumns: ["tablo_id"] + foreignKeyName: "fk_note_access_tablo_id"; + columns: ["tablo_id"]; + isOneToOne: false; + referencedRelation: "events_and_tablos"; + referencedColumns: ["tablo_id"]; }, { - foreignKeyName: "fk_note_access_tablo_id" - columns: ["tablo_id"] - isOneToOne: false - referencedRelation: "tablos" - referencedColumns: ["id"] + foreignKeyName: "fk_note_access_tablo_id"; + columns: ["tablo_id"]; + isOneToOne: false; + referencedRelation: "tablos"; + referencedColumns: ["id"]; }, { - foreignKeyName: "fk_note_access_tablo_id" - columns: ["tablo_id"] - isOneToOne: false - referencedRelation: "user_tablos" - referencedColumns: ["id"] + foreignKeyName: "fk_note_access_tablo_id"; + columns: ["tablo_id"]; + isOneToOne: false; + referencedRelation: "user_tablos"; + referencedColumns: ["id"]; }, - ] - } + ]; + }; notes: { Row: { - content: string | null - created_at: string | null - deleted_at: string | null - id: string - title: string - updated_at: string | null - user_id: string - } + content: string | null; + created_at: string | null; + deleted_at: string | null; + id: string; + title: string; + updated_at: string | null; + user_id: string; + }; Insert: { - content?: string | null - created_at?: string | null - deleted_at?: string | null - id?: string - title: string - updated_at?: string | null - user_id: string - } + content?: string | null; + created_at?: string | null; + deleted_at?: string | null; + id?: string; + title: string; + updated_at?: string | null; + user_id: string; + }; Update: { - content?: string | null - created_at?: string | null - deleted_at?: string | null - id?: string - title?: string - updated_at?: string | null - user_id?: string - } - Relationships: [] - } + content?: string | null; + created_at?: string | null; + deleted_at?: string | null; + id?: string; + title?: string; + updated_at?: string | null; + user_id?: string; + }; + Relationships: []; + }; notifications: { Row: { - action_type: string - actor_id: string | null - created_at: string - entity_id: string - entity_type: string - id: string - message: Json - metadata: Json | null - read_at: string | null - user_id: string - } + action_type: string; + actor_id: string | null; + created_at: string; + entity_id: string; + entity_type: string; + id: string; + message: Json; + metadata: Json | null; + read_at: string | null; + user_id: string; + }; Insert: { - action_type: string - actor_id?: string | null - created_at?: string - entity_id: string - entity_type: string - id?: string - message?: Json - metadata?: Json | null - read_at?: string | null - user_id: string - } + action_type: string; + actor_id?: string | null; + created_at?: string; + entity_id: string; + entity_type: string; + id?: string; + message?: Json; + metadata?: Json | null; + read_at?: string | null; + user_id: string; + }; Update: { - action_type?: string - actor_id?: string | null - created_at?: string - entity_id?: string - entity_type?: string - id?: string - message?: Json - metadata?: Json | null - read_at?: string | null - user_id?: string - } - Relationships: [] - } + action_type?: string; + actor_id?: string | null; + created_at?: string; + entity_id?: string; + entity_type?: string; + id?: string; + message?: Json; + metadata?: Json | null; + read_at?: string | null; + user_id?: string; + }; + Relationships: []; + }; profiles: { Row: { - avatar_url: string | null - email: string | null - first_name: string | null - id: string - is_temporary: boolean - last_name: string | null - last_signed_in: string | null - name: string | null - plan: Database["public"]["Enums"]["subscription_plan"] | null - short_user_id: string - } + avatar_url: string | null; + email: string | null; + first_name: string | null; + id: string; + is_temporary: boolean; + last_name: string | null; + last_signed_in: string | null; + name: string | null; + plan: Database["public"]["Enums"]["subscription_plan"] | null; + short_user_id: string; + }; Insert: { - avatar_url?: string | null - email?: string | null - first_name?: string | null - id: string - is_temporary?: boolean - last_name?: string | null - last_signed_in?: string | null - name?: string | null - plan?: Database["public"]["Enums"]["subscription_plan"] | null - short_user_id: string - } + avatar_url?: string | null; + email?: string | null; + first_name?: string | null; + id: string; + is_temporary?: boolean; + last_name?: string | null; + last_signed_in?: string | null; + name?: string | null; + plan?: Database["public"]["Enums"]["subscription_plan"] | null; + short_user_id: string; + }; Update: { - avatar_url?: string | null - email?: string | null - first_name?: string | null - id?: string - is_temporary?: boolean - last_name?: string | null - last_signed_in?: string | null - name?: string | null - plan?: Database["public"]["Enums"]["subscription_plan"] | null - short_user_id?: string - } - Relationships: [] - } + avatar_url?: string | null; + email?: string | null; + first_name?: string | null; + id?: string; + is_temporary?: boolean; + last_name?: string | null; + last_signed_in?: string | null; + name?: string | null; + plan?: Database["public"]["Enums"]["subscription_plan"] | null; + short_user_id?: string; + }; + Relationships: []; + }; shared_notes: { Row: { - created_at: string | null - is_public: boolean | null - note_id: string - updated_at: string | null - user_id: string - } + created_at: string | null; + is_public: boolean | null; + note_id: string; + updated_at: string | null; + user_id: string; + }; Insert: { - created_at?: string | null - is_public?: boolean | null - note_id: string - updated_at?: string | null - user_id: string - } + created_at?: string | null; + is_public?: boolean | null; + note_id: string; + updated_at?: string | null; + user_id: string; + }; Update: { - created_at?: string | null - is_public?: boolean | null - note_id?: string - updated_at?: string | null - user_id?: string - } + created_at?: string | null; + is_public?: boolean | null; + note_id?: string; + updated_at?: string | null; + user_id?: string; + }; Relationships: [ { - foreignKeyName: "fk_shared_notes_note_id" - columns: ["note_id"] - isOneToOne: true - referencedRelation: "notes" - referencedColumns: ["id"] + foreignKeyName: "fk_shared_notes_note_id"; + columns: ["note_id"]; + isOneToOne: true; + referencedRelation: "notes"; + referencedColumns: ["id"]; }, - ] - } + ]; + }; tablo_access: { Row: { - created_at: string | null - granted_by: string - id: number - is_active: boolean | null - is_admin: boolean | null - tablo_id: string - user_id: string - } + created_at: string | null; + granted_by: string; + id: number; + is_active: boolean | null; + is_admin: boolean | null; + tablo_id: string; + user_id: string; + }; Insert: { - created_at?: string | null - granted_by: string - id?: number - is_active?: boolean | null - is_admin?: boolean | null - tablo_id: string - user_id: string - } + created_at?: string | null; + granted_by: string; + id?: number; + is_active?: boolean | null; + is_admin?: boolean | null; + tablo_id: string; + user_id: string; + }; Update: { - created_at?: string | null - granted_by?: string - id?: number - is_active?: boolean | null - is_admin?: boolean | null - tablo_id?: string - user_id?: string - } + created_at?: string | null; + granted_by?: string; + id?: number; + is_active?: boolean | null; + is_admin?: boolean | null; + tablo_id?: string; + user_id?: string; + }; Relationships: [ { - foreignKeyName: "fk_tablo_access_tablo_id" - columns: ["tablo_id"] - isOneToOne: false - referencedRelation: "events_and_tablos" - referencedColumns: ["tablo_id"] + foreignKeyName: "fk_tablo_access_tablo_id"; + columns: ["tablo_id"]; + isOneToOne: false; + referencedRelation: "events_and_tablos"; + referencedColumns: ["tablo_id"]; }, { - foreignKeyName: "fk_tablo_access_tablo_id" - columns: ["tablo_id"] - isOneToOne: false - referencedRelation: "tablos" - referencedColumns: ["id"] + foreignKeyName: "fk_tablo_access_tablo_id"; + columns: ["tablo_id"]; + isOneToOne: false; + referencedRelation: "tablos"; + referencedColumns: ["id"]; }, { - foreignKeyName: "fk_tablo_access_tablo_id" - columns: ["tablo_id"] - isOneToOne: false - referencedRelation: "user_tablos" - referencedColumns: ["id"] + foreignKeyName: "fk_tablo_access_tablo_id"; + columns: ["tablo_id"]; + isOneToOne: false; + referencedRelation: "user_tablos"; + referencedColumns: ["id"]; }, { - foreignKeyName: "fk_tablo_access_user_id_from_profiles" - columns: ["user_id"] - isOneToOne: false - referencedRelation: "profiles" - referencedColumns: ["id"] + foreignKeyName: "fk_tablo_access_user_id_from_profiles"; + columns: ["user_id"]; + isOneToOne: false; + referencedRelation: "profiles"; + referencedColumns: ["id"]; }, - ] - } + ]; + }; tablo_invites: { Row: { - created_at: string - id: number - invite_token: string - invited_by: string - invited_email: string - is_pending: boolean - tablo_id: string - } + created_at: string; + id: number; + invite_token: string; + invited_by: string; + invited_email: string; + is_pending: boolean; + tablo_id: string; + }; Insert: { - created_at?: string - id?: number - invite_token: string - invited_by: string - invited_email: string - is_pending?: boolean - tablo_id: string - } + created_at?: string; + id?: number; + invite_token: string; + invited_by: string; + invited_email: string; + is_pending?: boolean; + tablo_id: string; + }; Update: { - created_at?: string - id?: number - invite_token?: string - invited_by?: string - invited_email?: string - is_pending?: boolean - tablo_id?: string - } + created_at?: string; + id?: number; + invite_token?: string; + invited_by?: string; + invited_email?: string; + is_pending?: boolean; + tablo_id?: string; + }; Relationships: [ { - foreignKeyName: "fk_tablo_invitations_tablo_id" - columns: ["tablo_id"] - isOneToOne: false - referencedRelation: "events_and_tablos" - referencedColumns: ["tablo_id"] + foreignKeyName: "fk_tablo_invitations_tablo_id"; + columns: ["tablo_id"]; + isOneToOne: false; + referencedRelation: "events_and_tablos"; + referencedColumns: ["tablo_id"]; }, { - foreignKeyName: "fk_tablo_invitations_tablo_id" - columns: ["tablo_id"] - isOneToOne: false - referencedRelation: "tablos" - referencedColumns: ["id"] + foreignKeyName: "fk_tablo_invitations_tablo_id"; + columns: ["tablo_id"]; + isOneToOne: false; + referencedRelation: "tablos"; + referencedColumns: ["id"]; }, { - foreignKeyName: "fk_tablo_invitations_tablo_id" - columns: ["tablo_id"] - isOneToOne: false - referencedRelation: "user_tablos" - referencedColumns: ["id"] + foreignKeyName: "fk_tablo_invitations_tablo_id"; + columns: ["tablo_id"]; + isOneToOne: false; + referencedRelation: "user_tablos"; + referencedColumns: ["id"]; }, - ] - } + ]; + }; tablos: { Row: { - color: string | null - created_at: string | null - deleted_at: string | null - id: string - image: string | null - name: string - owner_id: string - position: number - status: string - updated_at: string | null - } + color: string | null; + created_at: string | null; + deleted_at: string | null; + id: string; + image: string | null; + name: string; + owner_id: string; + position: number; + status: string; + updated_at: string | null; + }; Insert: { - color?: string | null - created_at?: string | null - deleted_at?: string | null - id?: string - image?: string | null - name: string - owner_id: string - position?: number - status?: string - updated_at?: string | null - } + color?: string | null; + created_at?: string | null; + deleted_at?: string | null; + id?: string; + image?: string | null; + name: string; + owner_id: string; + position?: number; + status?: string; + updated_at?: string | null; + }; Update: { - color?: string | null - created_at?: string | null - deleted_at?: string | null - id?: string - image?: string | null - name?: string - owner_id?: string - position?: number - status?: string - updated_at?: string | null - } - Relationships: [] - } + color?: string | null; + created_at?: string | null; + deleted_at?: string | null; + id?: string; + image?: string | null; + name?: string; + owner_id?: string; + position?: number; + status?: string; + updated_at?: string | null; + }; + Relationships: []; + }; tasks: { Row: { - assignee_id: string | null - created_at: string - description: string | null - id: string - position: number - status: Database["public"]["Enums"]["task_status"] - tablo_id: string - title: string - updated_at: string - } + assignee_id: string | null; + created_at: string; + description: string | null; + id: string; + is_parent: boolean; + parent_task_id: string | null; + position: number; + status: Database["public"]["Enums"]["task_status"]; + tablo_id: string; + title: string; + updated_at: string; + }; Insert: { - assignee_id?: string | null - created_at?: string - description?: string | null - id?: string - position?: number - status?: Database["public"]["Enums"]["task_status"] - tablo_id: string - title: string - updated_at?: string - } + assignee_id?: string | null; + created_at?: string; + description?: string | null; + id?: string; + is_parent?: boolean; + parent_task_id?: string | null; + position?: number; + status?: Database["public"]["Enums"]["task_status"]; + tablo_id: string; + title: string; + updated_at?: string; + }; Update: { - assignee_id?: string | null - created_at?: string - description?: string | null - id?: string - position?: number - status?: Database["public"]["Enums"]["task_status"] - tablo_id?: string - title?: string - updated_at?: string - } + assignee_id?: string | null; + created_at?: string; + description?: string | null; + id?: string; + is_parent?: boolean; + parent_task_id?: string | null; + position?: number; + status?: Database["public"]["Enums"]["task_status"]; + tablo_id?: string; + title?: string; + updated_at?: string; + }; Relationships: [ { - foreignKeyName: "tasks_tablo_id_fkey" - columns: ["tablo_id"] - isOneToOne: false - referencedRelation: "events_and_tablos" - referencedColumns: ["tablo_id"] + foreignKeyName: "tasks_parent_task_id_fkey"; + columns: ["parent_task_id"]; + isOneToOne: false; + referencedRelation: "tasks"; + referencedColumns: ["id"]; }, { - foreignKeyName: "tasks_tablo_id_fkey" - columns: ["tablo_id"] - isOneToOne: false - referencedRelation: "tablos" - referencedColumns: ["id"] + foreignKeyName: "tasks_parent_task_id_fkey"; + columns: ["parent_task_id"]; + isOneToOne: false; + referencedRelation: "tasks_with_assignee"; + referencedColumns: ["id"]; }, { - foreignKeyName: "tasks_tablo_id_fkey" - columns: ["tablo_id"] - isOneToOne: false - referencedRelation: "user_tablos" - referencedColumns: ["id"] + foreignKeyName: "tasks_tablo_id_fkey"; + columns: ["tablo_id"]; + isOneToOne: false; + referencedRelation: "events_and_tablos"; + referencedColumns: ["tablo_id"]; }, - ] - } + { + foreignKeyName: "tasks_tablo_id_fkey"; + columns: ["tablo_id"]; + isOneToOne: false; + referencedRelation: "tablos"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "tasks_tablo_id_fkey"; + columns: ["tablo_id"]; + isOneToOne: false; + referencedRelation: "user_tablos"; + referencedColumns: ["id"]; + }, + ]; + }; user_introductions: { Row: { - config: Json - created_at: string | null - updated_at: string | null - user_id: string - } + config: Json; + created_at: string | null; + updated_at: string | null; + user_id: string; + }; Insert: { - config?: Json - created_at?: string | null - updated_at?: string | null - user_id: string - } + config?: Json; + created_at?: string | null; + updated_at?: string | null; + user_id: string; + }; Update: { - config?: Json - created_at?: string | null - updated_at?: string | null - user_id?: string - } - Relationships: [] - } - } + config?: Json; + created_at?: string | null; + updated_at?: string | null; + user_id?: string; + }; + Relationships: []; + }; + }; Views: { events_and_tablos: { Row: { - description: string | null - end_time: string | null - event_id: string | null - start_date: string | null - start_time: string | null - tablo_color: string | null - tablo_id: string | null - tablo_name: string | null - tablo_status: string | null - title: string | null - } - Relationships: [] - } + description: string | null; + end_time: string | null; + event_id: string | null; + start_date: string | null; + start_time: string | null; + tablo_color: string | null; + tablo_id: string | null; + tablo_name: string | null; + tablo_status: string | null; + title: string | null; + }; + Relationships: []; + }; tasks_with_assignee: { Row: { - assignee_avatar: string | null - assignee_id: string | null - assignee_name: string | null - created_at: string | null - description: string | null - id: string | null - position: number | null - status: Database["public"]["Enums"]["task_status"] | null - tablo_id: string | null - title: string | null - updated_at: string | null - } + assignee_avatar: string | null; + assignee_id: string | null; + assignee_name: string | null; + created_at: string | null; + description: string | null; + id: string | null; + is_parent: boolean | null; + parent_task_id: string | null; + position: number | null; + status: Database["public"]["Enums"]["task_status"] | null; + tablo_id: string | null; + title: string | null; + updated_at: string | null; + }; Relationships: [ { - foreignKeyName: "tasks_tablo_id_fkey" - columns: ["tablo_id"] - isOneToOne: false - referencedRelation: "events_and_tablos" - referencedColumns: ["tablo_id"] + foreignKeyName: "tasks_parent_task_id_fkey"; + columns: ["parent_task_id"]; + isOneToOne: false; + referencedRelation: "tasks"; + referencedColumns: ["id"]; }, { - foreignKeyName: "tasks_tablo_id_fkey" - columns: ["tablo_id"] - isOneToOne: false - referencedRelation: "tablos" - referencedColumns: ["id"] + foreignKeyName: "tasks_parent_task_id_fkey"; + columns: ["parent_task_id"]; + isOneToOne: false; + referencedRelation: "tasks_with_assignee"; + referencedColumns: ["id"]; }, { - foreignKeyName: "tasks_tablo_id_fkey" - columns: ["tablo_id"] - isOneToOne: false - referencedRelation: "user_tablos" - referencedColumns: ["id"] + foreignKeyName: "tasks_tablo_id_fkey"; + columns: ["tablo_id"]; + isOneToOne: false; + referencedRelation: "events_and_tablos"; + referencedColumns: ["tablo_id"]; }, - ] - } + { + foreignKeyName: "tasks_tablo_id_fkey"; + columns: ["tablo_id"]; + isOneToOne: false; + referencedRelation: "tablos"; + referencedColumns: ["id"]; + }, + { + foreignKeyName: "tasks_tablo_id_fkey"; + columns: ["tablo_id"]; + isOneToOne: false; + referencedRelation: "user_tablos"; + referencedColumns: ["id"]; + }, + ]; + }; user_tablos: { Row: { - access_level: string | null - color: string | null - created_at: string | null - deleted_at: string | null - id: string | null - image: string | null - is_admin: boolean | null - name: string | null - position: number | null - status: string | null - user_id: string | null - } + access_level: string | null; + color: string | null; + created_at: string | null; + deleted_at: string | null; + id: string | null; + image: string | null; + is_admin: boolean | null; + name: string | null; + position: number | null; + status: string | null; + user_id: string | null; + }; Relationships: [ { - foreignKeyName: "fk_tablo_access_user_id_from_profiles" - columns: ["user_id"] - isOneToOne: false - referencedRelation: "profiles" - referencedColumns: ["id"] + foreignKeyName: "fk_tablo_access_user_id_from_profiles"; + columns: ["user_id"]; + isOneToOne: false; + referencedRelation: "profiles"; + referencedColumns: ["id"]; }, - ] - } - } + ]; + }; + }; Functions: { - generate_random_string: { Args: { length?: number }; Returns: string } + generate_random_string: { Args: { length?: number }; Returns: string }; get_my_active_subscription: { - Args: never + Args: never; Returns: { - billing_interval: string - cancel_at_period_end: boolean - currency: string - current_period_end: string - current_period_start: string - first_name: string - last_name: string - plan: Database["public"]["Enums"]["subscription_plan"] - product_name: string - status: string - subscription_id: string - unit_amount: number - user_email: string - user_id: string - }[] - } + billing_interval: string; + cancel_at_period_end: boolean; + currency: string; + current_period_end: string; + current_period_start: string; + first_name: string; + last_name: string; + plan: Database["public"]["Enums"]["subscription_plan"]; + product_name: string; + status: string; + subscription_id: string; + unit_amount: number; + user_email: string; + user_id: string; + }[]; + }; get_stripe_prices: { - Args: never + Args: never; Returns: { - active: boolean - created: number - currency: string - id: string - metadata: Json - product: string - recurring: Json - unit_amount: number - }[] - } + active: boolean; + created: number; + currency: string; + id: string; + metadata: Json; + product: string; + recurring: Json; + unit_amount: number; + }[]; + }; get_stripe_products: { - Args: never + Args: never; Returns: { - active: boolean - created: number - description: string - id: string - metadata: Json - name: string - }[] - } + active: boolean; + created: number; + description: string; + id: string; + metadata: Json; + name: string; + }[]; + }; get_user_stripe_customer: { - Args: never + Args: never; Returns: { - created: number - email: string - id: string - metadata: Json - user_id: string - }[] - } + created: number; + email: string; + id: string; + metadata: Json; + user_id: string; + }[]; + }; get_user_stripe_customer_id: { - Args: { user_uuid: string } - Returns: string - } + Args: { user_uuid: string }; + Returns: string; + }; get_user_stripe_subscriptions: { - Args: never + Args: never; Returns: { - cancel_at_period_end: boolean - canceled_at: number - created: number - current_period_end: number - current_period_start: number - customer: string - id: string - metadata: Json - price_id: string - quantity: number - status: string - trial_end: Json - trial_start: Json - user_id: string - }[] - } + cancel_at_period_end: boolean; + canceled_at: number; + created: number; + current_period_end: number; + current_period_start: number; + customer: string; + id: string; + metadata: Json; + price_id: string; + quantity: number; + status: string; + trial_end: Json; + trial_start: Json; + user_id: string; + }[]; + }; get_user_subscription_status: { - Args: { user_uuid: string } + Args: { user_uuid: string }; Returns: { - cancel_at_period_end: boolean - current_period_end: number - current_period_start: number - plan: Database["public"]["Enums"]["subscription_plan"] - price_id: string - product_name: string - status: string - subscription_id: string - }[] - } - is_paying_user: { Args: { user_uuid: string }; Returns: boolean } - } + cancel_at_period_end: boolean; + current_period_end: number; + current_period_start: number; + plan: Database["public"]["Enums"]["subscription_plan"]; + price_id: string; + product_name: string; + status: string; + subscription_id: string; + }[]; + }; + is_paying_user: { Args: { user_uuid: string }; Returns: boolean }; + }; Enums: { - devis_status: "draft" | "sent" | "accepted" | "rejected" | "expired" - subscription_plan: "none" | "trial" | "standard" - task_status: "todo" | "in_progress" | "in_review" | "done" - } + devis_status: "draft" | "sent" | "accepted" | "rejected" | "expired"; + subscription_plan: "none" | "trial" | "standard"; + task_status: "todo" | "in_progress" | "in_review" | "done"; + }; CompositeTypes: { time_range: { - start_time: string | null - end_time: string | null - } - } - } -} + start_time: string | null; + end_time: string | null; + }; + }; + }; +}; -type DatabaseWithoutInternals = Omit +type DatabaseWithoutInternals = Omit; -type DefaultSchema = DatabaseWithoutInternals[Extract] +type DefaultSchema = DatabaseWithoutInternals[Extract]; export type Tables< DefaultSchemaTableNameOrOptions extends | keyof (DefaultSchema["Tables"] & DefaultSchema["Views"]) | { schema: keyof DatabaseWithoutInternals }, TableName extends DefaultSchemaTableNameOrOptions extends { - schema: keyof DatabaseWithoutInternals + schema: keyof DatabaseWithoutInternals; } ? keyof (DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] & DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Views"]) : never = never, > = DefaultSchemaTableNameOrOptions extends { - schema: keyof DatabaseWithoutInternals + schema: keyof DatabaseWithoutInternals; } ? (DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] & DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Views"])[TableName] extends { - Row: infer R + Row: infer R; } ? R : never - : DefaultSchemaTableNameOrOptions extends keyof (DefaultSchema["Tables"] & - DefaultSchema["Views"]) - ? (DefaultSchema["Tables"] & - DefaultSchema["Views"])[DefaultSchemaTableNameOrOptions] extends { - Row: infer R + : DefaultSchemaTableNameOrOptions extends keyof (DefaultSchema["Tables"] & DefaultSchema["Views"]) + ? (DefaultSchema["Tables"] & DefaultSchema["Views"])[DefaultSchemaTableNameOrOptions] extends { + Row: infer R; } ? R : never - : never + : never; export type TablesInsert< DefaultSchemaTableNameOrOptions extends | keyof DefaultSchema["Tables"] | { schema: keyof DatabaseWithoutInternals }, TableName extends DefaultSchemaTableNameOrOptions extends { - schema: keyof DatabaseWithoutInternals + schema: keyof DatabaseWithoutInternals; } ? keyof DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] : never = never, > = DefaultSchemaTableNameOrOptions extends { - schema: keyof DatabaseWithoutInternals + schema: keyof DatabaseWithoutInternals; } ? DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"][TableName] extends { - Insert: infer I + Insert: infer I; } ? I : never : DefaultSchemaTableNameOrOptions extends keyof DefaultSchema["Tables"] ? DefaultSchema["Tables"][DefaultSchemaTableNameOrOptions] extends { - Insert: infer I + Insert: infer I; } ? I : never - : never + : never; export type TablesUpdate< DefaultSchemaTableNameOrOptions extends | keyof DefaultSchema["Tables"] | { schema: keyof DatabaseWithoutInternals }, TableName extends DefaultSchemaTableNameOrOptions extends { - schema: keyof DatabaseWithoutInternals + schema: keyof DatabaseWithoutInternals; } ? keyof DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] : never = never, > = DefaultSchemaTableNameOrOptions extends { - schema: keyof DatabaseWithoutInternals + schema: keyof DatabaseWithoutInternals; } ? DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"][TableName] extends { - Update: infer U + Update: infer U; } ? U : never : DefaultSchemaTableNameOrOptions extends keyof DefaultSchema["Tables"] ? DefaultSchema["Tables"][DefaultSchemaTableNameOrOptions] extends { - Update: infer U + Update: infer U; } ? U : never - : never + : never; export type Enums< DefaultSchemaEnumNameOrOptions extends | keyof DefaultSchema["Enums"] | { schema: keyof DatabaseWithoutInternals }, EnumName extends DefaultSchemaEnumNameOrOptions extends { - schema: keyof DatabaseWithoutInternals + schema: keyof DatabaseWithoutInternals; } ? keyof DatabaseWithoutInternals[DefaultSchemaEnumNameOrOptions["schema"]]["Enums"] : never = never, > = DefaultSchemaEnumNameOrOptions extends { - schema: keyof DatabaseWithoutInternals + schema: keyof DatabaseWithoutInternals; } ? DatabaseWithoutInternals[DefaultSchemaEnumNameOrOptions["schema"]]["Enums"][EnumName] : DefaultSchemaEnumNameOrOptions extends keyof DefaultSchema["Enums"] ? DefaultSchema["Enums"][DefaultSchemaEnumNameOrOptions] - : never + : never; export type CompositeTypes< PublicCompositeTypeNameOrOptions extends | keyof DefaultSchema["CompositeTypes"] | { schema: keyof DatabaseWithoutInternals }, CompositeTypeName extends PublicCompositeTypeNameOrOptions extends { - schema: keyof DatabaseWithoutInternals + schema: keyof DatabaseWithoutInternals; } ? keyof DatabaseWithoutInternals[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"] : never = never, > = PublicCompositeTypeNameOrOptions extends { - schema: keyof DatabaseWithoutInternals + schema: keyof DatabaseWithoutInternals; } ? DatabaseWithoutInternals[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"][CompositeTypeName] : PublicCompositeTypeNameOrOptions extends keyof DefaultSchema["CompositeTypes"] ? DefaultSchema["CompositeTypes"][PublicCompositeTypeNameOrOptions] - : never + : never; export const Constants = { public: { @@ -996,4 +1024,4 @@ export const Constants = { task_status: ["todo", "in_progress", "in_review", "done"], }, }, -} as const +} as const; diff --git a/packages/shared-types/src/index.ts b/packages/shared-types/src/index.ts index f3cd25a..21cc520 100644 --- a/packages/shared-types/src/index.ts +++ b/packages/shared-types/src/index.ts @@ -18,6 +18,7 @@ export type { export type { DragItem, DropResult, + Etape, KanbanBoard, KanbanColumn, KanbanColumnUpdate, diff --git a/packages/shared-types/src/kanban.types.ts b/packages/shared-types/src/kanban.types.ts index 33c596d..1fe76c7 100644 --- a/packages/shared-types/src/kanban.types.ts +++ b/packages/shared-types/src/kanban.types.ts @@ -3,7 +3,15 @@ import type { RemoveNullFromObject } from "./utils.js"; export type TaskStatus = "todo" | "in_progress" | "in_review" | "done"; -export type KanbanTask = RemoveNullFromObject, "id" | "tablo_id">; +export type KanbanTask = RemoveNullFromObject< + Tables<"tasks_with_assignee">, + "id" | "tablo_id" | "is_parent" +>; + +export type Etape = RemoveNullFromObject< + Tables<"tasks">, + "id" | "tablo_id" | "title" | "is_parent" +>; export interface KanbanColumn { id: string; diff --git a/packages/shared/src/hooks/public.ts b/packages/shared/src/hooks/public.ts index 5e17b48..5a0cdb9 100644 --- a/packages/shared/src/hooks/public.ts +++ b/packages/shared/src/hooks/public.ts @@ -32,7 +32,7 @@ export function usePublicSlots(api: AxiosInstance, shortUserId: string, standard }>({ queryKey: ["public-slots", shortUserId, standardName], queryFn: async () => { - const res = await api.get(`/api/public/slots/${shortUserId}/${standardName}`); + const res = await api.get(`/api/v1/public/slots/${shortUserId}/${standardName}`); if (res.status !== 200) { throw new Error("Failed to fetch public slots"); }