fix: generate board slug for new boards

This commit is contained in:
Henry
2025-01-12 09:32:31 +00:00
parent 2df54f03bb
commit 765db90570
5 changed files with 46 additions and 8 deletions

View File

@@ -1,8 +1,9 @@
import { useForm } from "react-hook-form";
import { HiXMark } from "react-icons/hi2";
import { type NewBoardInput } from "@kan/api/types";
import type { NewBoardInput } from "@kan/api/types";
import Button from "~/components/Button";
import { useModal } from "~/providers/modal";
import { useWorkspace } from "~/providers/workspace";
import { api } from "~/utils/api";
@@ -15,7 +16,7 @@ export function NewBoardForm() {
const { register, handleSubmit } = useForm<NewBoardInput>({
defaultValues: {
name: "",
workspacePublicId: workspace?.publicId || "",
workspacePublicId: workspace.publicId || "",
},
});
@@ -57,12 +58,9 @@ export function NewBoardForm() {
<div className="mt-12 flex items-center justify-end border-t border-light-600 px-5 pb-5 pt-5 dark:border-dark-600">
<div>
<button
type="submit"
className="inline-flex w-full justify-center rounded-md bg-light-1000 px-3 py-2 text-sm font-semibold text-light-50 shadow-sm focus-visible:outline-none dark:bg-dark-1000 dark:text-dark-50"
>
<Button type="submit" isLoading={createBoard.isPending}>
Create board
</button>
</Button>
</div>
</div>
</form>

View File

@@ -6,6 +6,7 @@ import * as cardRepo from "@kan/db/repository/card.repo";
import * as activityRepo from "@kan/db/repository/cardActivity.repo";
import * as listRepo from "@kan/db/repository/list.repo";
import * as workspaceRepo from "@kan/db/repository/workspace.repo";
import { generateSlug, generateUID } from "@kan/utils";
import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc";
@@ -141,7 +142,18 @@ export const boardRouter = createTRPCRouter({
code: "NOT_FOUND",
});
let slug = generateSlug(input.name);
const isSlugUnique = await boardRepo.isSlugUnique(ctx.db, {
slug,
workspaceId: workspace.id,
});
if (!isSlugUnique) slug = `${slug}-${generateUID()}`;
const result = await boardRepo.create(ctx.db, {
publicId: generateUID(),
slug,
name: input.name,
createdBy: userId,
workspaceId: workspace.id,

View File

@@ -210,20 +210,23 @@ export const getWithLatestListIndexByPublicId = async (
export const create = async (
db: SupabaseClient<Database>,
boardInput: {
publicId?: string;
name: string;
createdBy: string;
workspaceId: number;
importId?: number;
slug: string;
},
) => {
const { data } = await db
.from("board")
.insert({
publicId: generateUID(),
publicId: boardInput.publicId ?? generateUID(),
name: boardInput.name,
createdBy: boardInput.createdBy,
workspaceId: boardInput.workspaceId,
importId: boardInput.importId,
slug: boardInput.slug,
})
.select(`id, publicId, name`)
.limit(1)
@@ -277,3 +280,19 @@ export const hardDelete = async (
return result;
};
export const isSlugUnique = async (
db: SupabaseClient<Database>,
args: { slug: string; workspaceId: number },
) => {
const { data } = await db
.from("board")
.select("slug")
.eq("slug", args.slug)
.eq("workspaceId", args.workspaceId)
.is("deletedAt", null)
.limit(1)
.single();
return !data;
};

View File

@@ -0,0 +1,8 @@
export function generateSlug(text: string): string {
return text
.toLowerCase()
.trim()
.replace(/[^\w\s-]/g, "") // Remove special characters
.replace(/\s+/g, "-") // Replace spaces with hyphens
.replace(/-+/g, "-"); // Remove consecutive hyphens
}

View File

@@ -1,3 +1,4 @@
export const name = "utils";
export { generateUID } from "./generateUID";
export { generateSlug } from "./generateSlug";