Refactor appName generation in dashboard components

- Updated the appName generation logic in `AddApplication`, `AddCompose`, and `AddDatabase` components to use the `slugify` function for improved consistency and readability.
- Enhanced the `slugify` function to return a default value of "service" if the input is empty, ensuring robustness in name generation.
- Improved project name validation in `handle-project.tsx` to enforce stricter rules on naming conventions.
This commit is contained in:
Mauricio Siu
2025-05-04 20:14:49 -06:00
parent 7e365e1947
commit 86b56e2597
5 changed files with 24 additions and 18 deletions

View File

@@ -145,10 +145,8 @@ export const AddApplication = ({ projectId, projectName }: Props) => {
{...field} {...field}
onChange={(e) => { onChange={(e) => {
const val = e.target.value?.trim() || ""; const val = e.target.value?.trim() || "";
form.setValue( const serviceName = slugify(val);
"appName", form.setValue("appName", `${slug}-${serviceName}`);
`${slug}-${val.toLowerCase().replaceAll(" ", "-")}`,
);
field.onChange(val); field.onChange(val);
}} }}
/> />

View File

@@ -152,10 +152,8 @@ export const AddCompose = ({ projectId, projectName }: Props) => {
{...field} {...field}
onChange={(e) => { onChange={(e) => {
const val = e.target.value?.trim() || ""; const val = e.target.value?.trim() || "";
form.setValue( const serviceName = slugify(val);
"appName", form.setValue("appName", `${slug}-${serviceName}`);
`${slug}-${val.toLowerCase()}`,
);
field.onChange(val); field.onChange(val);
}} }}
/> />

View File

@@ -363,10 +363,9 @@ export const AddDatabase = ({ projectId, projectName }: Props) => {
{...field} {...field}
onChange={(e) => { onChange={(e) => {
const val = e.target.value?.trim() || ""; const val = e.target.value?.trim() || "";
form.setValue( const serviceName = slugify(val);
"appName", console.log(serviceName);
`${slug}-${val.toLowerCase()}`, form.setValue("appName", `${slug}-${serviceName}`);
);
field.onChange(val); field.onChange(val);
}} }}
/> />

View File

@@ -33,12 +33,23 @@ import { z } from "zod";
const AddProjectSchema = z.object({ const AddProjectSchema = z.object({
name: z name: z
.string() .string()
.min(1, { .min(1, "Project name is required")
message: "Name is required", .refine(
}) (name) => {
.regex(/^[a-zA-Z]/, { const trimmedName = name.trim();
const validNameRegex =
/^[\p{L}\p{N}_-][\p{L}\p{N}\s_-]*[\p{L}\p{N}_-]$/u;
return validNameRegex.test(trimmedName);
},
{
message:
"Project name must start and end with a letter, number, hyphen or underscore. Spaces are allowed in between.",
},
)
.refine((name) => !/^\d/.test(name.trim()), {
message: "Project name cannot start with a number", message: "Project name cannot start with a number",
}), })
.transform((name) => name.trim()),
description: z.string().optional(), description: z.string().optional(),
}); });

View File

@@ -5,7 +5,7 @@ export const slugify = (text: string | undefined) => {
return ""; return "";
} }
const cleanedText = text.trim().replace(/[^a-zA-Z0-9\s]/g, ""); const cleanedText = text.trim().replace(/[^a-zA-Z0-9\s]/g, "") || "service";
return slug(cleanedText, { return slug(cleanedText, {
lower: true, lower: true,