Improve slug description, regex and replace useState with watch

This commit is contained in:
carlosmonastyrski
2025-03-10 08:18:43 -03:00
parent 699e03c1a9
commit 20bd2ca71c
3 changed files with 13 additions and 11 deletions
+1 -1
View File
@@ -460,7 +460,7 @@ export const PROJECTS = {
name: "The new name of the project.", name: "The new name of the project.",
projectDescription: "An optional description label for the project.", projectDescription: "An optional description label for the project.",
autoCapitalization: "Disable or enable auto-capitalization for the project.", autoCapitalization: "Disable or enable auto-capitalization for the project.",
slug: "An optional slug for the project. (must be unique within the server)" slug: "An optional slug for the project. (must be unique within the organization)"
}, },
GET_KEY: { GET_KEY: {
workspaceId: "The ID of the project to get the key from." workspaceId: "The ID of the project to get the key from."
@@ -311,6 +311,10 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
slug: z slug: z
.string() .string()
.trim() .trim()
.regex(
/^[a-z0-9]+(?:[_-][a-z0-9]+)*$/,
"Project slug can only contain lowercase letters and numbers, with optional single hyphens (-) or underscores (_) between words. Cannot start or end with a hyphen or underscore."
)
.max(64, { message: "Slug must be 64 characters or fewer" }) .max(64, { message: "Slug must be 64 characters or fewer" })
.optional() .optional()
.describe(PROJECTS.UPDATE.slug) .describe(PROJECTS.UPDATE.slug)
@@ -1,4 +1,4 @@
import { useEffect, useState } from "react"; import { useEffect } from "react";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod"; import { z } from "zod";
@@ -23,7 +23,10 @@ const formSchemaWithSlug = baseFormSchema.extend({
.string() .string()
.min(1, "Required") .min(1, "Required")
.max(64, "Too long, maximum length is 64 characters") .max(64, "Too long, maximum length is 64 characters")
.regex(/^[a-zA-Z0-9-]+$/, "Only letters, numbers and hyphens are allowed") .regex(
/^[a-z0-9]+(?:[_-][a-z0-9]+)*$/,
"Project slug can only contain lowercase letters and numbers, with optional single hyphens (-) or underscores (_) between words. Cannot start or end with a hyphen or underscore."
)
}); });
type BaseFormData = z.infer<typeof baseFormSchema>; type BaseFormData = z.infer<typeof baseFormSchema>;
@@ -35,13 +38,13 @@ type Props = {
export const ProjectOverviewChangeSection = ({ showSlugField = false }: Props) => { export const ProjectOverviewChangeSection = ({ showSlugField = false }: Props) => {
const { currentWorkspace } = useWorkspace(); const { currentWorkspace } = useWorkspace();
const [currentSlug, setCurrentSlug] = useState(currentWorkspace?.slug);
const { mutateAsync, isPending } = useUpdateProject(); const { mutateAsync, isPending } = useUpdateProject();
const { handleSubmit, control, reset, watch } = useForm<BaseFormData | FormDataWithSlug>({
const { handleSubmit, control, reset } = useForm<BaseFormData | FormDataWithSlug>({
resolver: zodResolver(showSlugField ? formSchemaWithSlug : baseFormSchema) resolver: zodResolver(showSlugField ? formSchemaWithSlug : baseFormSchema)
}); });
const currentSlug = showSlugField ? watch("slug") : currentWorkspace?.slug;
useEffect(() => { useEffect(() => {
if (currentWorkspace) { if (currentWorkspace) {
reset({ reset({
@@ -49,7 +52,6 @@ export const ProjectOverviewChangeSection = ({ showSlugField = false }: Props) =
description: currentWorkspace.description ?? "", description: currentWorkspace.description ?? "",
...(showSlugField && { slug: currentWorkspace.slug }) ...(showSlugField && { slug: currentWorkspace.slug })
}); });
setCurrentSlug(currentWorkspace.slug);
} }
}, [currentWorkspace, showSlugField]); }, [currentWorkspace, showSlugField]);
@@ -67,10 +69,6 @@ export const ProjectOverviewChangeSection = ({ showSlugField = false }: Props) =
}) })
}); });
if (showSlugField && "slug" in data) {
setCurrentSlug(data.slug);
}
createNotification({ createNotification({
text: "Successfully updated project overview", text: "Successfully updated project overview",
type: "success" type: "success"