From d1e27b5b83309e6e48be3c60140f96b4cd0ec218 Mon Sep 17 00:00:00 2001 From: Henry Date: Sun, 3 Nov 2024 21:05:58 +0000 Subject: [PATCH] feat: openapi enhancements --- bun.lockb | Bin 349922 -> 361015 bytes package.json | 2 +- src/pages/api/v1/{[trpc].ts => [...trpc].ts} | 0 src/providers/board.tsx | 16 +++-- src/server/api/routers/auth.ts | 15 +++- src/server/api/routers/board.ts | 33 ++++++--- src/server/api/routers/card.ts | 64 ++++++++++++------ src/server/api/routers/import.ts | 10 ++- src/server/api/routers/label.ts | 34 +++++++--- src/server/api/routers/list.ts | 27 +++++--- src/server/api/routers/member.ts | 22 +++++- src/server/api/routers/workspace.ts | 29 ++++++-- src/server/api/trpc.ts | 18 +++-- src/server/db/repository/board.repo.ts | 4 +- src/server/db/repository/label.repo.ts | 4 +- src/utils/supabase/api.ts | 31 ++++----- src/views/board/index.tsx | 7 +- .../components/DeleteLabelConfirmation.tsx | 4 +- src/views/card/components/LabelForm.tsx | 6 +- src/views/card/components/LabelSelector.tsx | 2 +- src/views/card/components/ListSelector.tsx | 6 +- src/views/card/components/MemberSelector.tsx | 2 +- src/views/card/index.tsx | 6 +- .../components/DeleteMemberConfirmation.tsx | 3 + src/views/members/index.tsx | 2 +- 25 files changed, 231 insertions(+), 116 deletions(-) rename src/pages/api/v1/{[trpc].ts => [...trpc].ts} (100%) diff --git a/bun.lockb b/bun.lockb index f110354474563f976c45173b81ef67a53203db6a..5c4e77ed39b159dac1c33582284b53f00749dfee 100755 GIT binary patch delta 89159 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 O=i#y8t-2n=Q~y6fXMwc< delta 81778 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 = ({ }; const updateList = ({ - boardId, - listId, + listPublicId, currentIndex, newIndex, }: ReorderListInput) => { updateListMutation.mutate({ - boardId, - listId, + listPublicId, currentIndex, newIndex, }); }; - const updateCard = ({ cardId, newListId, newIndex }: ReorderCardInput) => { + const updateCard = ({ + cardPublicId, + newListPublicId, + newIndex, + }: ReorderCardInput) => { updateCardMutation.mutate({ - cardId, - newListId, + cardPublicId, + newListPublicId, newIndex, }); }; diff --git a/src/server/api/routers/auth.ts b/src/server/api/routers/auth.ts index 89a74615..d4e0d7a8 100644 --- a/src/server/api/routers/auth.ts +++ b/src/server/api/routers/auth.ts @@ -16,8 +16,12 @@ export const authRouter = createTRPCRouter({ .meta({ openapi: { method: "GET", - path: "/auth/user", + path: "/users/me", summary: "Get user", + description: + "Retrieves the currently authenticated user's profile information", + tags: ["Users"], + protect: true, }, }) .input(z.void()) @@ -52,8 +56,10 @@ export const authRouter = createTRPCRouter({ .meta({ openapi: { method: "POST", - path: "/auth/email", + path: "/auth/login/email", summary: "Login with email", + description: "Sends a login URL to the provided email address", + tags: ["Auth"], }, }) .input(z.object({ email: z.string() })) @@ -78,8 +84,11 @@ export const authRouter = createTRPCRouter({ .meta({ openapi: { method: "POST", - path: "/auth/oauth", + path: "/auth/login/oauth", summary: "Login with OAuth", + description: + "Initiates the login process for a user with the given OAuth provider", + tags: ["Auth"], }, }) .input(z.object({ provider: z.string() })) diff --git a/src/server/api/routers/board.ts b/src/server/api/routers/board.ts index e9561f0b..99d5539c 100644 --- a/src/server/api/routers/board.ts +++ b/src/server/api/routers/board.ts @@ -13,8 +13,11 @@ export const boardRouter = createTRPCRouter({ .meta({ openapi: { method: "GET", - path: "/board/{workspacePublicId}", + path: "/workspaces/{workspacePublicId}/boards", summary: "Get all boards", + description: "Retrieves all boards for a given workspace", + tags: ["Boards"], + protect: true, }, }) .input(z.object({ workspacePublicId: z.string().min(12) })) @@ -41,15 +44,18 @@ export const boardRouter = createTRPCRouter({ .meta({ openapi: { method: "GET", - path: "/board/{boardPublicId}", + path: "/boards/{boardPublicId}", summary: "Get board by public ID", + description: "Retrieves a board by its public ID", + tags: ["Boards"], + protect: true, }, }) .input( z.object({ boardPublicId: z.string().min(12), - members: z.array(z.string().min(12)), - labels: z.array(z.string().min(12)), + members: z.array(z.string().min(12)).optional(), + labels: z.array(z.string().min(12)).optional(), }), ) .output(z.custom>>()) @@ -58,8 +64,8 @@ export const boardRouter = createTRPCRouter({ ctx.db, input.boardPublicId, { - members: input.members, - labels: input.labels, + members: input.members ?? [], + labels: input.labels ?? [], }, ); @@ -69,8 +75,11 @@ export const boardRouter = createTRPCRouter({ .meta({ openapi: { method: "POST", - path: "/board", + path: "/workspaces/{workspacePublicId}/boards", summary: "Create board", + description: "Creates a new board for a given workspace", + tags: ["Boards"], + protect: true, }, }) .input( @@ -118,8 +127,11 @@ export const boardRouter = createTRPCRouter({ .meta({ openapi: { method: "PUT", - path: "/board/{boardPublicId}", + path: "/boards/{boardPublicId}", summary: "Update board", + description: "Updates a board by its public ID", + tags: ["Boards"], + protect: true, }, }) .input( @@ -147,8 +159,11 @@ export const boardRouter = createTRPCRouter({ .meta({ openapi: { method: "DELETE", - path: "/board/{boardPublicId}", + path: "/boards/{boardPublicId}", summary: "Delete board", + description: "Deletes a board by its public ID", + tags: ["Boards"], + protect: true, }, }) .input( diff --git a/src/server/api/routers/card.ts b/src/server/api/routers/card.ts index fb4ae389..efd6546e 100644 --- a/src/server/api/routers/card.ts +++ b/src/server/api/routers/card.ts @@ -14,7 +14,10 @@ export const cardRouter = createTRPCRouter({ openapi: { summary: "Create a card", method: "POST", - path: "/", + path: "/cards", + description: "Creates a new card for a given list", + tags: ["Cards"], + protect: true, }, }) .input( @@ -128,8 +131,11 @@ export const cardRouter = createTRPCRouter({ .meta({ openapi: { summary: "Add or remove a label from a card", - method: "POST", - path: "/{cardPublicId}/label/{labelPublicId}", + method: "PUT", + path: "/cards/{cardPublicId}/labels/{labelPublicId}", + description: "Adds or removes a label from a card", + tags: ["Cards"], + protect: true, }, }) .input( @@ -184,8 +190,10 @@ export const cardRouter = createTRPCRouter({ .meta({ openapi: { summary: "Add or remove a member from a card", - method: "POST", - path: "/{cardPublicId}/member/{workspaceMemberPublicId}", + method: "PUT", + path: "/cards/{cardPublicId}/members/{workspaceMemberPublicId}", + description: "Adds or removes a member from a card", + tags: ["Cards"], }, }) .input( @@ -242,12 +250,15 @@ export const cardRouter = createTRPCRouter({ byId: protectedProcedure .meta({ openapi: { - summary: "Get a card by ID", + summary: "Get a card by public ID", method: "GET", - path: "/{id}", + path: "/cards/{cardPublicId}", + description: "Retrieves a card by its public ID", + tags: ["Cards"], + protect: true, }, }) - .input(z.object({ id: z.string().min(12) })) + .input(z.object({ cardPublicId: z.string().min(12) })) .output( z.custom< Awaited> @@ -256,12 +267,12 @@ export const cardRouter = createTRPCRouter({ .query(async ({ ctx, input }) => { const result = await cardRepo.getWithListAndMembersByPublicId( ctx.db, - input.id, + input.cardPublicId, ); if (!result) throw new TRPCError({ - message: `Card with ID ${input.id} not found`, + message: `Card with public ID ${input.cardPublicId} not found`, code: "NOT_FOUND", }); @@ -272,12 +283,15 @@ export const cardRouter = createTRPCRouter({ openapi: { summary: "Update a card", method: "PUT", - path: "/{cardId}", + path: "/cards/{cardPublicId}", + description: "Updates a card by its public ID", + tags: ["Cards"], + protect: true, }, }) .input( z.object({ - cardId: z.string().min(12), + cardPublicId: z.string().min(12), title: z.string().min(1), description: z.string(), }), @@ -295,7 +309,7 @@ export const cardRouter = createTRPCRouter({ const result = await cardRepo.update( ctx.db, { title: input.title, description: input.description }, - { cardPublicId: input.cardId }, + { cardPublicId: input.cardPublicId }, ); if (!result) @@ -311,7 +325,10 @@ export const cardRouter = createTRPCRouter({ openapi: { summary: "Delete a card", method: "DELETE", - path: "/{cardPublicId}", + path: "/cards/{cardPublicId}", + description: "Deletes a card by its public ID", + tags: ["Cards"], + protect: true, }, }) .input( @@ -359,14 +376,17 @@ export const cardRouter = createTRPCRouter({ .meta({ openapi: { summary: "Reorder a card", - method: "POST", - path: "/{cardId}/reorder", + method: "PUT", + path: "/cards/{cardPublicId}/reorder", + description: "Reorders the position of a card in a given list", + tags: ["Cards"], + protect: true, }, }) .input( z.object({ - cardId: z.string().min(12), - newListId: z.string().min(12), + cardPublicId: z.string().min(12), + newListPublicId: z.string().min(12), newIndex: z.number().optional(), }), ) @@ -382,12 +402,12 @@ export const cardRouter = createTRPCRouter({ const card = await cardRepo.getCardWithListByPublicId( ctx.db, - input.cardId, + input.cardPublicId, ); if (!card?.list) throw new TRPCError({ - message: `Card with public ID ${input.cardId} not found`, + message: `Card with public ID ${input.cardPublicId} not found`, code: "NOT_FOUND", }); @@ -398,12 +418,12 @@ export const cardRouter = createTRPCRouter({ const newList = await listRepo.getWithCardsByPublicId( ctx.db, - input.newListId, + input.newListPublicId, ); if (!newList) throw new TRPCError({ - message: `List with public ID ${input.newListId} not found`, + message: `List with public ID ${input.newListPublicId} not found`, code: "NOT_FOUND", }); diff --git a/src/server/api/routers/import.ts b/src/server/api/routers/import.ts index f06e4208..f839197c 100644 --- a/src/server/api/routers/import.ts +++ b/src/server/api/routers/import.ts @@ -41,7 +41,10 @@ export const importRouter = createTRPCRouter({ openapi: { summary: "Get boards from Trello", method: "GET", - path: "/boards", + path: "/imports/trello/boards", + description: "Retrieves all boards from Trello", + tags: ["Imports"], + protect: true, }, }) .input( @@ -91,7 +94,10 @@ export const importRouter = createTRPCRouter({ openapi: { summary: "Import boards from Trello", method: "POST", - path: "/import", + path: "/imports/trello/import", + description: "Imports boards from Trello", + tags: ["Imports"], + protect: true, }, }) .input( diff --git a/src/server/api/routers/label.ts b/src/server/api/routers/label.ts index 353c59ed..9e9c3537 100644 --- a/src/server/api/routers/label.ts +++ b/src/server/api/routers/label.ts @@ -12,17 +12,20 @@ export const labelRouter = createTRPCRouter({ openapi: { summary: "Get a label by public ID", method: "GET", - path: "/{publicId}", + path: "/labels/{labelPublicId}", + description: "Retrieves a label by its public ID", + tags: ["Labels"], + protect: true, }, }) - .input(z.object({ publicId: z.string().min(12) })) + .input(z.object({ labelPublicId: z.string().min(12) })) .output(z.custom>>()) .query(async ({ ctx, input }) => { - const label = await labelRepo.getByPublicId(ctx.db, input.publicId); + const label = await labelRepo.getByPublicId(ctx.db, input.labelPublicId); if (!label) throw new TRPCError({ - message: `Label with public ID ${input.publicId} not found`, + message: `Label with public ID ${input.labelPublicId} not found`, code: "NOT_FOUND", }); @@ -33,7 +36,10 @@ export const labelRouter = createTRPCRouter({ openapi: { summary: "Create a label", method: "POST", - path: "/create", + path: "/labels", + description: "Creates a new label", + tags: ["Labels"], + protect: true, }, }) .input( @@ -84,12 +90,15 @@ export const labelRouter = createTRPCRouter({ openapi: { summary: "Update a label", method: "PUT", - path: "/{publicId}", + path: "/labels/{labelPublicId}", + description: "Updates a label by its public ID", + tags: ["Labels"], + protect: true, }, }) .input( z.object({ - publicId: z.string().min(12), + labelPublicId: z.string().min(12), name: z.string().min(1).max(36), colourCode: z.string().length(7), }), @@ -105,17 +114,20 @@ export const labelRouter = createTRPCRouter({ openapi: { summary: "Delete a label", method: "DELETE", - path: "/{publicId}", + path: "/labels/{labelPublicId}", + description: "Deletes a label by its public ID", + tags: ["Labels"], + protect: true, }, }) - .input(z.object({ publicId: z.string().min(12) })) + .input(z.object({ labelPublicId: z.string().min(12) })) .output(z.object({ success: z.boolean() })) .mutation(async ({ ctx, input }) => { - const label = await labelRepo.getByPublicId(ctx.db, input.publicId); + const label = await labelRepo.getByPublicId(ctx.db, input.labelPublicId); if (!label) throw new TRPCError({ - message: `Label with public ID ${input.publicId} not found`, + message: `Label with public ID ${input.labelPublicId} not found`, code: "NOT_FOUND", }); diff --git a/src/server/api/routers/list.ts b/src/server/api/routers/list.ts index 87516fdc..b3ae3db3 100644 --- a/src/server/api/routers/list.ts +++ b/src/server/api/routers/list.ts @@ -13,7 +13,10 @@ export const listRouter = createTRPCRouter({ openapi: { summary: "Create a list", method: "POST", - path: "/list/create", + path: "/lists", + description: "Creates a new list for a given board", + tags: ["Lists"], + protect: true, }, }) .input( @@ -65,24 +68,26 @@ export const listRouter = createTRPCRouter({ openapi: { summary: "Reorder a list", method: "POST", - path: "/{listId}/reorder", + path: "/lists/{listPublicId}/reorder", + description: "Reorders the position of a list", + tags: ["Lists"], + protect: true, }, }) .input( z.object({ - boardId: z.string().min(12), - listId: z.string().min(12), + listPublicId: z.string().min(12), currentIndex: z.number(), newIndex: z.number(), }), ) .output(z.custom>>()) .mutation(async ({ ctx, input }) => { - const list = await listRepo.getByPublicId(ctx.db, input.listId); + const list = await listRepo.getByPublicId(ctx.db, input.listPublicId); if (!list) throw new TRPCError({ - message: `List with public ID ${input.listId} not found`, + message: `List with public ID ${input.listPublicId} not found`, code: "NOT_FOUND", }); @@ -106,7 +111,10 @@ export const listRouter = createTRPCRouter({ openapi: { summary: "Delete a list", method: "DELETE", - path: "/{listPublicId}", + path: "/lists/{listPublicId}", + description: "Deletes a list by its public ID", + tags: ["Lists"], + protect: true, }, }) .input( @@ -158,7 +166,10 @@ export const listRouter = createTRPCRouter({ openapi: { summary: "Update a list", method: "PUT", - path: "/list/{listPublicId}", + path: "/lists/{listPublicId}", + description: "Updates a list by its public ID", + tags: ["Lists"], + protect: true, }, }) .input( diff --git a/src/server/api/routers/member.ts b/src/server/api/routers/member.ts index b286f03f..171ffe8b 100644 --- a/src/server/api/routers/member.ts +++ b/src/server/api/routers/member.ts @@ -15,7 +15,10 @@ export const memberRouter = createTRPCRouter({ openapi: { summary: "Invite a member to a workspace", method: "POST", - path: "/invite", + path: "/workspaces/{workspacePublicId}/members/invite", + description: "Invites a member to a workspace", + tags: ["Members"], + protect: true, }, }) .input( @@ -144,11 +147,15 @@ export const memberRouter = createTRPCRouter({ openapi: { summary: "Delete a member from a workspace", method: "DELETE", - path: "/{memberPublicId}", + path: "/workspaces/{workspacePublicId}/members/{memberPublicId}", + description: "Deletes a member from a workspace", + tags: ["Members"], + protect: true, }, }) .input( z.object({ + workspacePublicId: z.string().min(12), memberPublicId: z.string().min(12), }), ) @@ -162,6 +169,17 @@ export const memberRouter = createTRPCRouter({ code: "UNAUTHORIZED", }); + const workspace = await workspaceRepo.getByPublicId( + ctx.db, + input.workspacePublicId, + ); + + if (!workspace) + throw new TRPCError({ + message: `Workspace with public ID ${input.workspacePublicId} not found`, + code: "NOT_FOUND", + }); + const member = await memberRepo.getByPublicId( ctx.db, input.memberPublicId, diff --git a/src/server/api/routers/workspace.ts b/src/server/api/routers/workspace.ts index c8ae67f8..75a91078 100644 --- a/src/server/api/routers/workspace.ts +++ b/src/server/api/routers/workspace.ts @@ -10,7 +10,10 @@ export const workspaceRouter = createTRPCRouter({ openapi: { summary: "Get all workspaces", method: "GET", - path: "/", + path: "/workspaces", + description: "Retrieves all workspaces for the authenticated user", + tags: ["Workspaces"], + protect: true, }, }) .input(z.void()) @@ -35,10 +38,13 @@ export const workspaceRouter = createTRPCRouter({ openapi: { summary: "Get a workspace by public ID", method: "GET", - path: "/workspace/{publicId}", + path: "/workspaces/{workspacePublicId}", + description: "Retrieves a workspace by its public ID", + tags: ["Workspaces"], + protect: true, }, }) - .input(z.object({ publicId: z.string().min(12) })) + .input(z.object({ workspacePublicId: z.string().min(12) })) .output( z.custom< Awaited> @@ -47,7 +53,7 @@ export const workspaceRouter = createTRPCRouter({ .query(async ({ ctx, input }) => { const result = await workspaceRepo.getByPublicIdWithMembers( ctx.db, - input.publicId, + input.workspacePublicId, ); if (!result) @@ -63,7 +69,10 @@ export const workspaceRouter = createTRPCRouter({ openapi: { summary: "Create a workspace", method: "POST", - path: "/workspace/create", + path: "/workspaces", + description: "Creates a new workspace", + tags: ["Workspaces"], + protect: true, }, }) .input( @@ -100,7 +109,10 @@ export const workspaceRouter = createTRPCRouter({ openapi: { summary: "Update a workspace", method: "PUT", - path: "/workspace/{workspacePublicId}", + path: "/workspaces/{workspacePublicId}", + description: "Updates a workspace by its public ID", + tags: ["Workspaces"], + protect: true, }, }) .input( @@ -124,7 +136,10 @@ export const workspaceRouter = createTRPCRouter({ openapi: { summary: "Delete a workspace", method: "DELETE", - path: "/workspace/{workspacePublicId}", + path: "/workspaces/{workspacePublicId}", + description: "Deletes a workspace by its public ID", + tags: ["Workspaces"], + protect: true, }, }) .input(z.object({ workspacePublicId: z.string().min(12) })) diff --git a/src/server/api/trpc.ts b/src/server/api/trpc.ts index 4d8a59bf..310defc5 100644 --- a/src/server/api/trpc.ts +++ b/src/server/api/trpc.ts @@ -79,16 +79,22 @@ export const createTRPCContext = async ({ return createInnerTRPCContext({ db, adminDb, user }); }; -export const createRESTContext = async ({ - req, - res, -}: CreateNextContextOptions) => { - const db = createNextApiClient(req, res); +export const createRESTContext = async ({ req }: CreateNextContextOptions) => { + const db = createNextApiClient(req); const adminDb = createTRPCAdminClient(); + const authHeader = req.headers.authorization; + const accessToken = authHeader?.startsWith("Bearer ") + ? authHeader.substring(7) + : null; + + if (!accessToken) { + return createInnerTRPCContext({ db, adminDb, user: null }); + } + const { data: { user }, - } = await db.auth.getUser(); + } = await db.auth.getUser(accessToken); return createInnerTRPCContext({ db, adminDb, user }); }; diff --git a/src/server/db/repository/board.repo.ts b/src/server/db/repository/board.repo.ts index 0a93eda5..b15c7c0d 100644 --- a/src/server/db/repository/board.repo.ts +++ b/src/server/db/repository/board.repo.ts @@ -84,14 +84,12 @@ export const getByPublicId = async ( query = query.in("lists.cards.members.publicId", filters.members); } - const { data, error } = await query + const { data } = await query .order("index", { foreignTable: "list", ascending: true }) .order("index", { foreignTable: "list.card", ascending: true }) .limit(1) .single(); - console.log(error); - return data; }; diff --git a/src/server/db/repository/label.repo.ts b/src/server/db/repository/label.repo.ts index b0d322f8..320bd7a6 100644 --- a/src/server/db/repository/label.repo.ts +++ b/src/server/db/repository/label.repo.ts @@ -63,7 +63,7 @@ export const getByPublicId = async ( export const update = async ( db: SupabaseClient, labelInput: { - publicId: string; + labelPublicId: string; name: string; colourCode: string; }, @@ -74,7 +74,7 @@ export const update = async ( name: labelInput.name, colourCode: labelInput.colourCode, }) - .eq("publicId", labelInput.publicId); + .eq("publicId", labelInput.labelPublicId); return data; }; diff --git a/src/utils/supabase/api.ts b/src/utils/supabase/api.ts index 0f8f2715..3f7cf8a3 100644 --- a/src/utils/supabase/api.ts +++ b/src/utils/supabase/api.ts @@ -6,7 +6,7 @@ import { import { RequestCookies } from "@edge-runtime/cookies"; import { type Database } from "~/types/database.types"; -import { type NextApiRequest, type NextApiResponse } from "next"; +import { type NextApiRequest } from "next"; import { type NextRequest, type NextResponse } from "next/server"; export function createNextClient(req: NextRequest, res: NextResponse) { @@ -31,26 +31,25 @@ export function createNextClient(req: NextRequest, res: NextResponse) { return supabase; } -export function createNextApiClient( - _req: NextApiRequest, - _res: NextApiResponse, -) { +export function createNextApiClient(req: NextApiRequest) { + const authHeader = req.headers.authorization; + const accessToken = authHeader?.startsWith("Bearer ") + ? authHeader.substring(7) + : null; + const supabase = createServerClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.SUPABASE_SERVICE_API_KEY!, { - cookies: { - get(_name: string) { - // return req.cookies.get(name)?.value; - return ""; - }, - set(_name: string, _value: string, _options: CookieOptions) { - // res.headers.append("Set-Cookie", serialize(name, value, options)); - }, - remove(_name: string, _options: CookieOptions) { - // res.headers.append("Set-Cookie", serialize(name, "", options)); - }, + auth: { + persistSession: false, + ...(accessToken && { + autoRefreshToken: false, + detectSessionInUrl: false, + access_token: accessToken, + }), }, + cookies: {}, }, ); diff --git a/src/views/board/index.tsx b/src/views/board/index.tsx index 634f503c..e59fb2ab 100644 --- a/src/views/board/index.tsx +++ b/src/views/board/index.tsx @@ -104,8 +104,7 @@ export default function BoardPage() { } updateList({ - boardId, - listId: draggableId, + listPublicId: draggableId, currentIndex: source.index, newIndex: destination.index, }); @@ -128,8 +127,8 @@ export default function BoardPage() { } updateCard({ - cardId: draggableId, - newListId: destination.droppableId, + cardPublicId: draggableId, + newListPublicId: destination.droppableId, newIndex: destination.index, }); } diff --git a/src/views/card/components/DeleteLabelConfirmation.tsx b/src/views/card/components/DeleteLabelConfirmation.tsx index 5f2d39ec..a6ba53bd 100644 --- a/src/views/card/components/DeleteLabelConfirmation.tsx +++ b/src/views/card/components/DeleteLabelConfirmation.tsx @@ -15,7 +15,7 @@ export function DeleteLabelConfirmation({ const { closeModal } = useModal(); const { showPopup } = usePopup(); - const refetchCard = () => utils.card.byId.refetch({ id: cardPublicId }); + const refetchCard = () => utils.card.byId.refetch({ cardPublicId }); const deleteLabelMutation = api.label.delete.useMutation({ onSuccess: () => refetchCard(), @@ -29,7 +29,7 @@ export function DeleteLabelConfirmation({ const handleDeleteLabel = () => { closeModal(); deleteLabelMutation.mutate({ - publicId: labelPublicId, + labelPublicId, }); }; diff --git a/src/views/card/components/LabelForm.tsx b/src/views/card/components/LabelForm.tsx index a1335067..90270ea4 100644 --- a/src/views/card/components/LabelForm.tsx +++ b/src/views/card/components/LabelForm.tsx @@ -44,7 +44,7 @@ export function LabelForm({ const label = api.label.byPublicId.useQuery( { - publicId: entityId, + labelPublicId: entityId, }, { enabled: isEdit && !!entityId, @@ -62,7 +62,7 @@ export function LabelForm({ }, }); - const refetchCard = () => utils.card.byId.refetch({ id: cardPublicId }); + const refetchCard = () => utils.card.byId.refetch({ cardPublicId }); const isCreateAnotherEnabled = watch("isCreateAnotherEnabled"); @@ -101,7 +101,7 @@ export function LabelForm({ if (isEdit) { updateLabel.mutate({ - publicId: label.data?.publicId ?? "", + labelPublicId: label.data?.publicId ?? "", name: values.name, colourCode: values.colour.code, }); diff --git a/src/views/card/components/LabelSelector.tsx b/src/views/card/components/LabelSelector.tsx index 3a8b6707..8861cae9 100644 --- a/src/views/card/components/LabelSelector.tsx +++ b/src/views/card/components/LabelSelector.tsx @@ -27,7 +27,7 @@ export default function LabelSelector({ const { openModal } = useModal(); const utils = api.useUtils(); - const refetchCard = () => utils.card.byId.refetch({ id: cardPublicId }); + const refetchCard = () => utils.card.byId.refetch({ cardPublicId }); const addOrRemoveLabel = api.card.addOrRemoveLabel.useMutation({ onSuccess: async () => { diff --git a/src/views/card/components/ListSelector.tsx b/src/views/card/components/ListSelector.tsx index 83eba488..b9e7fe0c 100644 --- a/src/views/card/components/ListSelector.tsx +++ b/src/views/card/components/ListSelector.tsx @@ -20,7 +20,7 @@ export default function ListSelector({ }: ListSelectorProps) { const utils = api.useUtils(); - const refetchCard = () => utils.card.byId.refetch({ id: cardPublicId }); + const refetchCard = () => utils.card.byId.refetch({ cardPublicId }); const updateCardList = api.card.reorder.useMutation({ onSuccess: async () => { @@ -78,8 +78,8 @@ export default function ListSelector({ setValue(list.publicId, newValue); updateCardList.mutate({ - cardId: cardPublicId, - newListId: list.publicId, + cardPublicId, + newListPublicId: list.publicId, }); handleSubmit(onSubmit); diff --git a/src/views/card/components/MemberSelector.tsx b/src/views/card/components/MemberSelector.tsx index 966304ea..bc353334 100644 --- a/src/views/card/components/MemberSelector.tsx +++ b/src/views/card/components/MemberSelector.tsx @@ -24,7 +24,7 @@ export default function MemberSelector({ }: MemberSelectorProps) { const utils = api.useUtils(); - const refetchCard = () => utils.card.byId.refetch({ id: cardPublicId }); + const refetchCard = () => utils.card.byId.refetch({ cardPublicId }); const addOrRemoveMember = api.card.addOrRemoveMember.useMutation({ onSuccess: async () => { diff --git a/src/views/card/index.tsx b/src/views/card/index.tsx index b88bcc75..3de0495e 100644 --- a/src/views/card/index.tsx +++ b/src/views/card/index.tsx @@ -32,7 +32,9 @@ export default function CardPage() { ? params.cardId[0] : params?.cardId; - const { data, isLoading } = api.card.byId.useQuery({ id: cardId ?? "" }); + const { data, isLoading } = api.card.byId.useQuery({ + cardPublicId: cardId ?? "", + }); const board = data?.list?.board; const boardId = board?.publicId; @@ -85,7 +87,7 @@ export default function CardPage() { const onSubmit = (values: FormValues) => { updateCard.mutate({ - cardId: values.cardId, + cardPublicId: values.cardId, title: values.title, description: values.description, }); diff --git a/src/views/members/components/DeleteMemberConfirmation.tsx b/src/views/members/components/DeleteMemberConfirmation.tsx index f1cb7d57..b4ef19d9 100644 --- a/src/views/members/components/DeleteMemberConfirmation.tsx +++ b/src/views/members/components/DeleteMemberConfirmation.tsx @@ -1,12 +1,14 @@ import { api } from "~/utils/api"; import { useModal } from "~/providers/modal"; import { usePopup } from "~/providers/popup"; +import { useWorkspace } from "~/providers/workspace"; import Button from "~/components/Button"; export function DeleteMemberConfirmation() { const utils = api.useUtils(); const { closeModal, entityLabel, entityId } = useModal(); + const { workspace } = useWorkspace(); const { showPopup } = usePopup(); const deleteMember = api.member.delete.useMutation({ @@ -31,6 +33,7 @@ export function DeleteMemberConfirmation() { if (entityId) deleteMember.mutate({ memberPublicId: entityId, + workspacePublicId: workspace.publicId, }); }; diff --git a/src/views/members/index.tsx b/src/views/members/index.tsx index 5dd138d7..38166bd7 100644 --- a/src/views/members/index.tsx +++ b/src/views/members/index.tsx @@ -18,7 +18,7 @@ export default function MembersPage() { const { workspace } = useWorkspace(); const { data, isLoading } = api.workspace.byId.useQuery( - { publicId: workspace.publicId }, + { workspacePublicId: workspace.publicId }, // { enabled: workspace?.publicId ? true : false }, );