Skip to content

Commit fdff32b

Browse files
authored
Merge pull request #550 from trycompai/claudio/comp-fix-editor-panel-3
[dev] [claudfuen] claudio/comp-fix-editor-panel-3
2 parents c90f5e4 + c05ab4d commit fdff32b

20 files changed

+1734
-38
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
description:
3+
globs:
4+
alwaysApply: false
5+
---
6+
Rule: Shared Zod Schemas for Client & Server Validation in Next.js
7+
When implementing features that require data validation using Zod schemas on both the client-side (e.g., in a React form within a Client Component) and the server-side (e.g., within a Next.js Server Action):
8+
Centralize Schema Definitions:
9+
Define your Zod schemas in dedicated TypeScript files (e.g., src/lib/schemas/feature-schemas.ts, src/features/my-feature/schemas.ts, or a common schemas.ts if broadly applicable).
10+
These schema definition files should not include "use client" or "use server" directives, as they are meant to be neutral modules.
11+
Server Action Implementation ("use server" files):
12+
Server Action files (marked with "use server") must only export asynchronous functions.
13+
Import the required Zod schema(s) from your centralized schema file(s) into the Server Action file.
14+
Use the imported schema for robust server-side validation of any incoming data before processing or database operations. This is a critical security measure.
15+
Client Component Implementation ("use client" files):
16+
Import the same Zod schema(s) from your centralized schema file(s) into your Client Components that contain forms.
17+
Use the schema with a resolver (like zodResolver for react-hook-form) to enable client-side validation, providing immediate feedback to the user.
18+
When the form is submitted, call the appropriate Server Action, passing the validated (or raw) form data.
19+
Rationale:
20+
DRY (Don't Repeat Yourself): Maintains a single source of truth for validation logic, reducing redundancy and potential inconsistencies.
21+
Next.js Constraints: Adheres to the Next.js App Router constraint that "use server" files can only export async functions. Objects like Zod schemas cannot be directly exported from these files.
22+
Security: Ensures that all data is re-validated on the server, even if client-side validation is in place, as client-side checks can be bypassed.
23+
User Experience: Provides immediate validation feedback on the client, improving the form-filling experience.
24+
Example Workflow Outline:
25+
Schema Definition (feature-schemas.ts):
26+
Define the schema, e.g., export const myFeatureSchema = z.object({ /* ...schema details... / });
27+
Client Component (MyFeatureForm.tsx - 'use client'):
28+
Import the schema and the server action.
29+
Set up the form (e.g., react-hook-form) using the schema with its resolver.
30+
The form's onSubmit handler calls the server action.
31+
Server Action (my-feature-action.ts - "use server"):
32+
Mark the file with "use server".
33+
Import the schema.
34+
The exported async server action function receives form data, validates it using the schema, and then performs server-side operations.

.cursor/rules/react-code.mdc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ When writing React code follow these standards:
1010
- Always name files that export components in PascalCase
1111
- Always round corners to rounded-sm
1212
- Always try to keep components small and modular
13-
- Always use sonner instead of toast.
13+
- Always use sonner instead of toast.

.cursor/rules/server-actions.mdc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
description:
3+
globs: *.ts
4+
alwaysApply: false
5+
---
6+
- Never use safe server actions, always use regular simple server actions.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
'use client';
2+
3+
import { useState } from 'react';
4+
import PageLayout from "@/app/components/PageLayout";
5+
import { DataTable } from "@/app/components/DataTable";
6+
import { columns } from "./components/columns";
7+
import { CreateControlDialog } from './components/CreateControlDialog';
8+
import type { FrameworkEditorControlTemplate } from '@prisma/client';
9+
import { useRouter } from 'next/navigation';
10+
11+
interface ControlsClientPageProps {
12+
initialControls: FrameworkEditorControlTemplate[];
13+
}
14+
15+
export function ControlsClientPage({ initialControls }: ControlsClientPageProps) {
16+
const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);
17+
const router = useRouter(); // Uncomment if needed
18+
19+
const handleRowClick = (control: FrameworkEditorControlTemplate) => {
20+
router.push(`/controls/${control.id}`);
21+
};
22+
23+
return (
24+
<PageLayout breadcrumbs={[{ label: "Controls", href: "/controls" }]}>
25+
<DataTable
26+
data={initialControls}
27+
columns={columns}
28+
searchQueryParamName="controls-search"
29+
searchPlaceholder="Search controls..."
30+
onCreateClick={() => setIsCreateDialogOpen(true)}
31+
createButtonLabel="Create New Control"
32+
onRowClick={handleRowClick}
33+
/>
34+
<CreateControlDialog
35+
isOpen={isCreateDialogOpen}
36+
onOpenChange={setIsCreateDialogOpen}
37+
onControlCreated={() => {
38+
setIsCreateDialogOpen(false);
39+
}}
40+
/>
41+
</PageLayout>
42+
);
43+
}

0 commit comments

Comments
 (0)