Skip to content

[PCN-133] add setup#186

Open
nicofuentesg wants to merge 10 commits intotestingfrom
feature-setups
Open

[PCN-133] add setup#186
nicofuentesg wants to merge 10 commits intotestingfrom
feature-setups

Conversation

@nicofuentesg
Copy link
Collaborator

@nicofuentesg nicofuentesg commented Jun 5, 2025

This pull request introduces several changes, including updates to dependencies, configuration adjustments, and new features for managing "Setup" entities in the database. The most significant changes involve database schema modifications, new API actions, and dependency updates.

Database and Schema Changes:

  • Added a new Setup model in prisma/schema.prisma to replace the Post model, with fields for title, content, imageUrl, and relationships to User and Like. The Like model was updated to support associations with both Advise and Setup entities. ([[1]](https://github.com/programaconnosotros/pcn-website/pull/186/files#diff-5b443964f4f3a611682db8f7e02177b0a8c632b2039e2bd5e4dd7347815c565cR55-R69), [[2]](https://github.com/programaconnosotros/pcn-website/pull/186/files#diff-5b443964f4f3a611682db8f7e02177b0a8c632b2039e2bd5e4dd7347815c565cL114-R143))
  • Created migration scripts to drop the Post table, create the Setup table, and update the Like model with a unique constraint for userId and setupId. ([[1]](https://github.com/programaconnosotros/pcn-website/pull/186/files#diff-934dc67b17d5bcf8828d881759a8d1a73698533cd43e7abbc423c09f761a1feaR1-R27), [[2]](https://github.com/programaconnosotros/pcn-website/pull/186/files#diff-9911a920d0c58de00ee4ef34c1cfcfae5cc01024258bf77c2caaa5b8c1b32bffR1-R15))

New API Actions:

  • Added createSetup and deleteSetup server-side actions to handle the creation and deletion of Setup entities. These actions include user authentication checks and revalidation of related paths. ([[1]](https://github.com/programaconnosotros/pcn-website/pull/186/files#diff-6c80b88562f99837165fde6f15d67c01388afa0390df3a6be8bdc92cadacd559R1-R42), [[2]](https://github.com/programaconnosotros/pcn-website/pull/186/files#diff-bd32d9dc698659ab79df246251260ceb94b8dcc7cb0b3a8af4bac77c98400edbR1-R24))

Dependency Updates:

  • Added @supabase/ssr to package.json and updated pnpm-lock.yaml with several Supabase-related dependencies (@supabase/auth-js, @supabase/functions-js, etc.) to support server-side rendering and other functionalities. ([[1]](https://github.com/programaconnosotros/pcn-website/pull/186/files#diff-7ae45ad102eab3b6d7e7896acd08c427a9b25b346470d7bc6507b6481575d519R44), [[2]](https://github.com/programaconnosotros/pcn-website/pull/186/files#diff-32824c984905bb02bc7ffcef96a77addd1f1602cff71a11fbbfdd7f53ee026bbR1380-R1406), [[3]](https://github.com/programaconnosotros/pcn-website/pull/186/files#diff-32824c984905bb02bc7ffcef96a77addd1f1602cff71a11fbbfdd7f53ee026bbR4431-R4477))
  • Updated pnpm-lock.yaml with additional dependencies such as cookie, ws, and whatwg-url to support new features and improve compatibility. ([[1]](https://github.com/programaconnosotros/pcn-website/pull/186/files#diff-32824c984905bb02bc7ffcef96a77addd1f1602cff71a11fbbfdd7f53ee026bbR1815-R1818), [[2]](https://github.com/programaconnosotros/pcn-website/pull/186/files#diff-32824c984905bb02bc7ffcef96a77addd1f1602cff71a11fbbfdd7f53ee026bbR3370-R3381))

Configuration Changes:

  • Updated next.config.mjs to allow images from additional external domains (storage.aceternity.com and sltoipimgzzeegsdygra.supabase.co). ([next.config.mjsR17-R24](https://github.com/programaconnosotros/pcn-website/pull/186/files#diff-18c049b08c4a0f5ab451c598aeb2c4848bb9d7877b51ca3e5effb94a225814d2R17-R24))

Video Presentation

screen-recording-2025-06-05-at-24438-am_R6FyhhFz.mp4

Summary by CodeRabbit

  • New Features

    • Introduced a "Setups" section where users can create, edit, delete, and like setup posts with images, titles, and descriptions.
    • Added a modal interface for uploading and editing setups, including image upload with validation and preview.
    • Users can now like setups, with instant UI feedback and like counts.
    • Added a "Setups" menu item in the sidebar for easy navigation.
  • Improvements

    • Enhanced image optimization to support additional external sources.
  • Bug Fixes

    • Sidebar icon for "Cursos" updated for visual clarity.

…rations - Create setup sharing UI with image upload - Configure Supabase storage for setup images - Add setup listing and card components - Update Next.js config for Supabase image hosting - Implement setup creation and image upload flow
@nicofuentesg nicofuentesg requested a review from agustin-sanc June 5, 2025 05:54
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 5, 2025

Walkthrough

This update introduces a new "Setup" feature, including database schema changes, server actions, and a UI for users to create, edit, delete, and like setups with images. It adds Supabase SSR support, updates image optimization settings, and enhances the sidebar navigation. New validation schemas and React components support the full setup workflow.

Changes

File(s) Change Summary
next.config.mjs Added remote image patterns for storage.aceternity.com and Supabase domains.
package.json Added @supabase/ssr dependency.
prisma/migrations/20250609200043_add_setup_model/migration.sql,
prisma/schema.prisma
Introduced Setup model and relations; updated Like model for polymorphic likes; added constraints and indices.
src/actions/setup/create-setup.ts,
src/actions/setup/delete-setup.ts,
src/actions/setup/edit-setup.ts,
src/actions/setup/fetch-setups.ts,
src/actions/setup/like-setup.ts,
src/actions/setup/update-setup-image.ts
Added server actions for creating, editing, deleting, liking, fetching, and updating image for setups.
src/app/(platform)/setups/page.tsx Added new page component to display setups list with user session.
src/components/setup/setup-card.tsx New component for displaying individual setup cards with author, image, and like functionality.
src/components/setup/setups-list.tsx New component for listing setups, managing modals, and handling publish/edit/delete actions.
src/components/setup/upload-setup-modal.tsx New modal component for uploading or editing setups, including image upload to Supabase.
src/components/ui/app-sidebar.tsx Changed Cursos icon to Book, and added Setups menu item with Laptop icon.
src/schemas/setup-schema.ts Added Zod schema and type for validating setup form data.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI as SetupsList/SetupCard/UploadSetupModal
    participant Actions as Server Actions
    participant DB as Database

    User->>UI: Open Setups Page
    UI->>Actions: fetchSetups(page)
    Actions->>DB: Query setups with author and likes
    DB-->>Actions: Setups data
    Actions-->>UI: Setups data
    UI-->>User: Display setups

    User->>UI: Create/Edit/Delete/Like Setup
    UI->>Actions: createSetup/editSetup/deleteSetup/toggleLikeSetup
    Actions->>DB: Perform DB operation (create, update, delete, like)
    DB-->>Actions: Result
    Actions->>UI: Confirmation / Updated data
    UI-->>User: Update UI (optimistically if like)
Loading

Poem

🐰
In the meadow of code, new Setups now bloom,
With images bright, and likes that go zoom!
Upload, edit, or delete with delight,
Supabase helps keep your pictures just right.
Sidebar’s refreshed, the schemas are neat—
This rabbit’s quite proud of this new setup feat!

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Collaborator

@agustin-sanc agustin-sanc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Muy buen trabajo Nico! Visualmente esta espectacular! En cuanto al código creo que podemos mejorar la calidad bastante, te dejé varios comentarios para que los trabajemos, creo que son una linda oportunidad de aprendizaje varios de ellos

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Veo que esta PR incluye 3 migrations. Lo ideal es que una PR tenga solo una migration. Lo que podes hacer es borrar estas 3 y crear una nueva. Esa nueva que crees, va a tener todos los cambios necesarios para hacer en la base. Avisame y lo vemos por Discord.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

La elimine y la modifique en una sola PR.
Gracias por ofrecerme a ayudar en Discord.

- Move initial setups fetch to server component
- Remove client-side initial fetch
- Remove unnecessary loading state
- Reuse fetchSetups server action
@agustin-sanc
Copy link
Collaborator

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 5, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

♻️ Duplicate comments (3)
src/actions/setup/update-setup-image.ts (1)

1-1: Code appears properly formatted.

The past review comment mentioned missing Prettier formatting, but the current code appears to be properly formatted.

src/app/(platform)/setups/page.tsx (1)

22-22: Consider fetching setups directly from Prisma for better performance.

The past review comment about performance improvement is still valid. Currently, the page uses two different data fetching patterns which could be optimized.

Consider this approach for consistency and performance:

-  const setups = await fetchSetups(1);
+  const setups = await prisma.setup.findMany({
+    include: {
+      author: true,
+      likes: true,
+    },
+    orderBy: {
+      createdAt: 'desc',
+    },
+    take: 10, // or whatever page size you need
+  });
src/actions/setup/create-setup.ts (1)

1-1: Formato pendiente con Prettier

🧹 Nitpick comments (8)
src/app/(platform)/setups/page.tsx (1)

8-20: Consider consolidating data fetching patterns.

The page uses direct Prisma queries for session data but a server action for setups. This creates inconsistency in data fetching patterns.

For consistency, consider either:

  1. Using direct Prisma queries for both session and setups data
  2. Creating a server action for session data as well
src/components/setup/upload-setup-modal.tsx (2)

128-130: Use optional chaining for safer property access

Apply this diff to use optional chaining:

-    if (e.dataTransfer.files && e.dataTransfer.files[0]) {
+    if (e.dataTransfer.files?.[0]) {
       handleFile(e.dataTransfer.files[0]);
     }

134-136: Use optional chaining for safer property access

Apply this diff to use optional chaining:

-    if (e.target.files && e.target.files[0]) {
+    if (e.target.files?.[0]) {
       handleFile(e.target.files[0]);
     }
src/components/setup/setups-list.tsx (5)

33-33: Consider making the page parameter configurable instead of hardcoding it.

The hardcoded page number 1 limits the function's reusability and prevents proper pagination implementation.

-  const fetchSetupsData = async () => {
+  const fetchSetupsData = async (page: number = 1) => {
     try {
-      const data = await fetchSetups(1);
+      const data = await fetchSetups(page);
       setSetups(data);
     } catch (error) {
       toast.error('Error al cargar los setups');
     }
   };

84-85: Remove duplicate setShowAuthModal(false) call.

The setShowAuthModal(false) is called twice in the finally block, which is redundant.

     } finally {
-      setShowAuthModal(false);
       setSelectedSetup(null);
       setModalAction(null);
     }

178-182: Consider extracting the onSubmit handler to a separate function for better readability.

The inline handler function makes the JSX less readable and harder to test.

+  const handleUploadSubmit = () => {
+    setShowUploadModal(false);
+    setSetupToEdit(null);
+    fetchSetupsData();
+  };

-          onSubmit={() => {
-            setShowUploadModal(false);
-            setSetupToEdit(null);
-            fetchSetupsData();
-          }}
+          onSubmit={handleUploadSubmit}

193-200: Add proper JSX element type for the icon prop.

The icon prop should have a more specific type for better type safety.

 interface ModalSetupProps {
   showAuthModal: boolean;
   setShowAuthModal: (show: boolean) => void;
   title?: string;
   description?: string;
-  icon?: React.ReactNode;
+  icon?: React.ReactElement;
   onConfirm?: () => void;
 }

1-256: Overall component structure looks good, but consider adding error boundaries and loading states.

The component successfully implements the setup management functionality without react-query as requested in the past review comments. The integration with server actions is well done.

Consider adding:

  • Error boundaries to gracefully handle component-level errors
  • Loading states for better user experience during async operations
  • Proper pagination controls for setup navigation
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1acc15c and 545b514.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (16)
  • next.config.mjs (1 hunks)
  • package.json (1 hunks)
  • prisma/migrations/20250609200043_add_setup_model/migration.sql (1 hunks)
  • prisma/schema.prisma (3 hunks)
  • src/actions/setup/create-setup.ts (1 hunks)
  • src/actions/setup/delete-setup.ts (1 hunks)
  • src/actions/setup/edit-setup.ts (1 hunks)
  • src/actions/setup/fetch-setups.ts (1 hunks)
  • src/actions/setup/like-setup.ts (1 hunks)
  • src/actions/setup/update-setup-image.ts (1 hunks)
  • src/app/(platform)/setups/page.tsx (1 hunks)
  • src/components/setup/setup-card.tsx (1 hunks)
  • src/components/setup/setups-list.tsx (1 hunks)
  • src/components/setup/upload-setup-modal.tsx (1 hunks)
  • src/components/ui/app-sidebar.tsx (3 hunks)
  • src/schemas/setup-schema.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
src/actions/setup/create-setup.ts (1)
Learnt from: MauriJC
PR: programaconnosotros/pcn-website#17
File: src/app/(platform)/events/[id]/page.tsx:24-28
Timestamp: 2025-02-04T21:17:26.725Z
Learning: Event ID validation is handled through Prisma's findUnique method which safely returns null for invalid or non-existent IDs, making additional ID format validation unnecessary.
src/schemas/setup-schema.ts (1)
Learnt from: MauriJC
PR: programaconnosotros/pcn-website#17
File: src/components/events/event-card.tsx:19-20
Timestamp: 2025-02-04T22:05:03.472Z
Learning: The Event model in the PCN website uses Zod schema validation (@prisma/generated/zod) which ensures date fields contain valid dates, making additional date validation in the UI components unnecessary.
🧬 Code Graph Analysis (6)
src/actions/setup/fetch-setups.ts (1)
src/lib/constants.ts (1)
  • ADVISES_PER_PAGE (1-1)
src/actions/setup/edit-setup.ts (1)
src/schemas/setup-schema.ts (1)
  • setupSchema (3-15)
src/actions/setup/create-setup.ts (1)
src/schemas/setup-schema.ts (1)
  • setupSchema (3-15)
src/components/setup/upload-setup-modal.tsx (6)
src/actions/setup/edit-setup.ts (1)
  • editSetup (8-43)
src/actions/setup/create-setup.ts (1)
  • createSetup (8-42)
src/actions/setup/update-setup-image.ts (1)
  • updateSetupImage (6-14)
src/components/ui/dialog.tsx (4)
  • Dialog (94-94)
  • DialogContent (99-99)
  • DialogHeader (100-100)
  • DialogTitle (102-102)
src/components/ui/input.tsx (1)
  • Input (24-24)
src/components/ui/textarea.tsx (1)
  • Textarea (23-23)
src/components/setup/setup-card.tsx (2)
src/actions/setup/like-setup.ts (1)
  • toggleLikeSetup (7-50)
src/components/ui/avatar.tsx (3)
  • Avatar (47-47)
  • AvatarImage (47-47)
  • AvatarFallback (47-47)
src/components/setup/setups-list.tsx (5)
src/actions/setup/fetch-setups.ts (1)
  • fetchSetups (7-32)
src/actions/setup/delete-setup.ts (1)
  • deleteSetup (7-24)
src/components/setup/setup-card.tsx (1)
  • SetupCard (28-174)
src/components/setup/upload-setup-modal.tsx (1)
  • UploadSetupModal (42-358)
src/components/ui/dialog.tsx (4)
  • Dialog (94-94)
  • DialogContent (99-99)
  • DialogHeader (100-100)
  • DialogTitle (102-102)
🪛 Biome (1.9.4)
src/components/setup/upload-setup-modal.tsx

[error] 128-128: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 134-134: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (14)
package.json (1)

44-44: LGTM! Clean dependency addition.

The @supabase/ssr package addition aligns with the PR objectives to support server-side rendering with Supabase. The caret version range is appropriate.

src/components/ui/app-sidebar.tsx (3)

4-4: LGTM! Appropriate icon import.

The Book icon import supports the icon change for the "Cursos" menu item.


73-73: LGTM! Better semantic icon choice.

Changing the "Cursos" icon from Laptop to Book is more semantically appropriate for educational content.


93-97: LGTM! Clean navigation addition.

The new "Setups" menu item is properly configured with appropriate URL and icon. The Laptop icon is semantically appropriate for hardware/setup configurations.

next.config.mjs (1)

17-24: LGTM! Necessary image configuration for Setup feature.

The new remote image patterns support the Setup feature's image handling capabilities. Both use HTTPS which is good for security.

The Supabase hostname sltoipimgzzeegsdygra.supabase.co appears to be a specific deployment URL. Verify this is the correct long-term hostname and won't change with different environments.

src/app/(platform)/setups/page.tsx (1)

24-28: LGTM! Clean component structure.

The component structure and rendering logic are well-organized. The session and setups data are properly passed to the child component.

src/actions/setup/delete-setup.ts (1)

7-24: LGTM! Secure deletion with proper authentication.

The implementation correctly validates user authentication and uses both id and authorId in the deletion criteria, preventing users from deleting other users' setups. The cache revalidation ensures UI consistency after deletion.

src/actions/setup/fetch-setups.ts (1)

30-31: Verify pagination logic with the constant mismatch.

Ensure the pagination logic using ADVISES_PER_PAGE provides the expected page size for setups functionality.

src/actions/setup/like-setup.ts (1)

7-50: LGTM! Well-implemented toggle like functionality.

The implementation correctly handles authentication, uses proper upsert logic for toggling likes, and includes comprehensive error handling. The function appropriately doesn't return unnecessary success objects, following good practices.

src/schemas/setup-schema.ts (1)

3-17: LGTM! Well-structured validation schema.

The schema provides appropriate validation constraints for setup data:

  • Title is required with reasonable length limits
  • Description is optional with sensible max length
  • ImageUrl validation ensures valid URLs
  • Proper TypeScript type inference
src/actions/setup/edit-setup.ts (1)

17-21: Approve the validation logic with proper schema usage.

The validation correctly uses the setupSchema to parse form data and imageUrl, ensuring data integrity before database operations.

src/components/setup/setup-card.tsx (1)

28-73: Well-implemented optimistic updates for likes!

The optimistic update pattern with local state fallback provides excellent user experience by showing immediate feedback while handling potential errors gracefully.

prisma/schema.prisma (1)

55-68: Clean implementation of polymorphic likes pattern

The schema changes properly implement polymorphic relationships by making adviseId optional and adding setupId with appropriate unique constraints. This allows the Like model to reference either Advise or Setup entities cleanly.

Also applies to: 130-141

prisma/migrations/20250609200043_add_setup_model/migration.sql (1)

1-31: Migration properly implements the schema changes

The migration correctly creates the Setup table and modifies the Like table to support polymorphic relationships. The warning about potential duplicate values is expected when adding unique constraints.

import prisma from '@/lib/prisma';
import { revalidatePath } from 'next/cache';

export const updateSetupImage = async (setupId: string, imageUrl: string) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add authentication and authorization checks.

The function doesn't verify user authentication or authorization to update the setup. This could allow unauthorized users to modify setup images.

Consider adding authentication checks similar to other server actions in the codebase.

🤖 Prompt for AI Agents
In src/actions/setup/update-setup-image.ts at line 6, the updateSetupImage
function lacks authentication and authorization checks, risking unauthorized
modifications. Add code to verify the user's authentication status and confirm
they have permission to update the specified setup, following the pattern used
in other server actions in the codebase. This typically involves checking the
user's session or token and validating their access rights before proceeding
with the update.

Comment on lines +6 to +14
export const updateSetupImage = async (setupId: string, imageUrl: string) => {
await prisma.setup.update({
where: { id: setupId },
data: { imageUrl },
});

revalidatePath('/setups');
revalidatePath('/');
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add error handling and input validation.

The function lacks critical error handling and input validation, which could lead to runtime errors and security issues.

Apply this diff to improve robustness:

-export const updateSetupImage = async (setupId: string, imageUrl: string) => {
-  await prisma.setup.update({
-    where: { id: setupId },
-    data: { imageUrl },
-  });
-
-  revalidatePath('/setups');
-  revalidatePath('/');
-};
+export const updateSetupImage = async (setupId: string, imageUrl: string) => {
+  if (!setupId || !imageUrl) {
+    throw new Error('Setup ID and image URL are required');
+  }
+
+  try {
+    await prisma.setup.update({
+      where: { id: setupId },
+      data: { imageUrl },
+    });
+
+    revalidatePath('/setups');
+    revalidatePath('/');
+  } catch (error) {
+    console.error('Failed to update setup image:', error);
+    throw new Error('Failed to update setup image');
+  }
+};
🤖 Prompt for AI Agents
In src/actions/setup/update-setup-image.ts around lines 6 to 14, the
updateSetupImage function lacks error handling and input validation. Add checks
to ensure setupId and imageUrl are valid (e.g., non-empty strings) before
proceeding. Wrap the prisma.update call and revalidatePath calls in a try-catch
block to handle and log any errors gracefully, preventing unhandled exceptions
and improving robustness.

@@ -0,0 +1,32 @@
'use server';

import { ADVISES_PER_PAGE } from '@/lib/constants';
Copy link
Contributor

@coderabbitai coderabbitai bot Jul 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Inconsistent constant name for setups pagination.

The function imports ADVISES_PER_PAGE but uses it for setups pagination, which is semantically inconsistent.

Consider adding a dedicated constant for setups or renaming the existing constant to be more generic:

-import { ADVISES_PER_PAGE } from '@/lib/constants';
+import { ITEMS_PER_PAGE } from '@/lib/constants';

Or add a specific constant in src/lib/constants.ts:

+export const SETUPS_PER_PAGE = 1000;

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/actions/setup/fetch-setups.ts at line 3, the imported constant
ADVISES_PER_PAGE is used for setups pagination, causing semantic inconsistency.
To fix this, define a new constant specifically for setups pagination in
src/lib/constants.ts, such as SETUPS_PER_PAGE, and import that instead. This
will clarify the purpose of the constant and maintain consistent naming
conventions.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aquí si es mejor crear una variable nueva

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

@MauriJC Perfect! I agree that creating a new variable is the better approach for semantic clarity. Let me plan the implementation:

Task: Create SETUPS_PER_PAGE constant for semantic consistency

  • Add new SETUPS_PER_PAGE constant to constants file
  • Update import in fetch-setups.ts to use the new constant
  • Update the function to use the new constant

🏁 Script executed:

# First, let's find the constants file to see its current structure
fd "constants" --type f --extension ts --extension js

Length of output: 74


Perfect! I found the constants file. Now I can complete the implementation plan:

Task: Create SETUPS_PER_PAGE constant for semantic consistency

  • Add new SETUPS_PER_PAGE constant to constants file
  • Update import in fetch-setups.ts to use the new constant
  • Update the function to use the new constant

The implementation will create semantic consistency by using a dedicated SETUPS_PER_PAGE constant specifically for setups pagination, maintaining the same value (1000) for consistent behavior across the application.


🧬 Code Graph Analysis Results

Relevant snippet from src/lib/constants.ts (line 1)

export const ADVISES_PER_PAGE = 1000;

This constant is used in fetchSetups to determine the number of setups to fetch per page (take: ADVISES_PER_PAGE) and to calculate the offset for pagination (skip: (page - 1) * ADVISES_PER_PAGE).


⏳ Preparing changes...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A summary of the changes CodeRabbit can apply:

  • Add a new constant SETUPS_PER_PAGE to the constants file and update the fetch-setups.ts file to import and use this new constant for pagination parameters instead of ADVISES_PER_PAGE.

  • Add a new constant SETUPS_PER_PAGE with value 1000 to the constants file, update the import in fetch-setups.ts to use this new constant, and modify the pagination parameters to reference SETUPS_PER_PAGE instead of ADVISES_PER_PAGE.

  • ✅ Create PR with these edits
  • 📌 Create commit in current branch
  • 📋 Get copyable edits

where: { id, authorId: session.userId },
data: {
title: validatedData.title,
content: validatedData.description!,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Critical issue: Non-null assertion on optional field.

The code uses validatedData.description! but description is optional in the schema and could be undefined, leading to potential runtime errors.

Fix the optional field handling:

-      content: validatedData.description!,
+      content: validatedData.description || '',

Or update the schema to make description required if it's always expected to have a value.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
content: validatedData.description!,
content: validatedData.description || '',
🤖 Prompt for AI Agents
In src/actions/setup/edit-setup.ts at line 37, the code uses a non-null
assertion on the optional field validatedData.description!, which can cause
runtime errors if description is undefined. To fix this, either add a
conditional check to safely handle the case when description is undefined before
using it, or update the schema to make description a required field if it should
always have a value.

Comment on lines +31 to +38
const setup = await prisma.setup.create({
data: {
title: validatedData.title,
content: validatedData.description!,
imageUrl: validatedData.imageUrl,
author: { connect: { id: user.id } },
},
});
Copy link
Contributor

@coderabbitai coderabbitai bot Jul 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix potential runtime error with optional description field

The description field is optional in the schema, but you're using a non-null assertion operator (!) which could cause a runtime error if the description is undefined.

Apply this diff to safely handle the optional description:

   const setup = await prisma.setup.create({
     data: {
       title: validatedData.title,
-      content: validatedData.description!,
+      content: validatedData.description || '',
       imageUrl: validatedData.imageUrl,
       author: { connect: { id: user.id } },
     },
   });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const setup = await prisma.setup.create({
data: {
title: validatedData.title,
content: validatedData.description!,
imageUrl: validatedData.imageUrl,
author: { connect: { id: user.id } },
},
});
const setup = await prisma.setup.create({
data: {
title: validatedData.title,
content: validatedData.description || '',
imageUrl: validatedData.imageUrl,
author: { connect: { id: user.id } },
},
});
🤖 Prompt for AI Agents
In src/actions/setup/create-setup.ts around lines 31 to 38, the code uses a
non-null assertion operator on the optional description field, which can cause a
runtime error if description is undefined. To fix this, remove the non-null
assertion operator and safely assign the description field by either providing a
default value or conditionally including it only if it exists, ensuring no
undefined value is passed to content.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Por que en un lado se llama content y en el otro description?
Sugeriría cambiarle el nombre a description aquí y en el modelo para mejor cohesion

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

@MauriJC You're absolutely right about the naming inconsistency! This is indeed confusing and reduces code cohesion. Let me investigate how this field is used across the codebase to understand the full scope.


🏁 Script executed:

#!/bin/bash
# Search for usage of 'content' field in relation to Setup
echo "=== Searching for 'content' field usage in Setup-related code ==="
rg -A 3 -B 3 "content.*setup|setup.*content" --ignore-case

echo -e "\n=== Searching for 'description' field usage in Setup-related code ==="
rg -A 3 -B 3 "description.*setup|setup.*description" --ignore-case

echo -e "\n=== Checking Prisma schema Setup model ==="
ast-grep --pattern 'model Setup {
  $$$
}'

echo -e "\n=== Checking setupSchema definition ==="
ast-grep --pattern 'export const setupSchema = $$$'

Length of output: 4202


🏁 Script executed:

#!/bin/bash
# Get the actual Prisma schema Setup model definition
echo "=== Full Prisma schema Setup model ==="
cat prisma/schema.prisma | sed -n '/^model Setup/,/^}/p'

echo -e "\n=== Search for all actions that use content field ==="
rg -A 2 -B 2 "content.*validatedData|validatedData.*content"

echo -e "\n=== Check edit-setup action ==="
cat src/actions/setup/edit-setup.ts

Length of output: 4483


Perfect! Now I can see the full picture of the naming inconsistency. You're absolutely right - this creates unnecessary confusion and mapping complexity.

Current State Analysis

The inconsistency exists across multiple layers:

  1. Validation/Schema layer: Uses description (in setupSchema)
  2. Database layer: Uses content (in Prisma Setup model)
  3. Actions: Map validatedData.descriptioncontent field
  4. UI Components: Convert back and forth between the two names

This creates problematic mappings like:

// In setups-list.tsx - converting content back to description for editing
description: setup.content

// In actions - converting description to content for database
content: validatedData.description!

Two Solutions for Consistency

Looking at your codebase, I see that Advise and Comment models consistently use content throughout. You have two options:

Option 1: Rename to description (as you suggested)

  • More semantic and user-friendly
  • Matches the frontend terminology
  • Requires database migration + updates

Option 2: Rename to content (match existing pattern)

  • Consistent with Advise/Comment models in your codebase
  • Less database changes, more schema changes
  • Follows existing naming convention

Recommendation

I'd lean toward Option 1 (your suggestion) because:

  • "description" is more semantically correct for user-facing content
  • It matches what users see in forms
  • The Setup entity seems more content-descriptive than the shorter Advise model

Would you like me to help plan the changes needed for either approach? The scope would include:

  • Prisma schema update
  • Database migration
  • Action files updates
  • Component updates
  • Type definitions

🧬 Code Graph Analysis Results

Possibly relevant snippets from src/schemas/setup-schema.ts (lines 3-15)

export const setupSchema = z.object({
  title: z
    .string()
    .min(1, 'El título es requerido')
    .max(45, 'El título no puede tener más de 45 caracteres')
    .trim(),
  description: z
    .string()
    .max(250, 'La descripción no puede tener más de 250 caracteres')
    .trim()
    .optional(),
  imageUrl: z.string().url('URL de imagen inválida').min(1, 'La imagen es requerida'),
});

This schema defines the validation rules for the setup data, including a description field.


File: src/actions/setup/create-setup.ts (lines 1-44)

'use server';

import prisma from '@/lib/prisma';
import { setupSchema } from '@/schemas/setup-schema';
import { revalidatePath } from 'next/cache';
import { cookies } from 'next/headers';

export const createSetup = async (formData: FormData, imageUrl: string) => {
  const validatedData = setupSchema.parse({
    title: formData.get('title'),
    description: formData.get('description'),
    imageUrl: imageUrl,
  });

  const sessionId = cookies().get('sessionId');

  if (!sessionId) throw new Error('Not authenticated');

  const session = await prisma.session.findUnique({
    where: { id: sessionId.value },
  });

  if (!session) throw new Error('Session not found');

  const user = await prisma.user.findUnique({
    where: { id: session.userId },
  });

  if (!user) throw new Error('User not found');

  const setup = await prisma.setup.create({
    data: {
      title: validatedData.title,
      content: validatedData.description!,  // Note: here 'description' is assigned to 'content'
      imageUrl: validatedData.imageUrl,
      author: { connect: { id: user.id } },
    },
  });
  revalidatePath('/setups');
  revalidatePath('/');
  return setup.id;
};

This function validates input data using setupSchema (which uses description), but when creating the database record, it assigns validatedData.description to the content field in the Prisma setup model. This shows the naming difference between the input/validation layer (description) and the database model (content).


✏️ Learnings added
Learnt from: MauriJC
PR: programaconnosotros/pcn-website#186
File: src/actions/setup/create-setup.ts:31-38
Timestamp: 2025-07-14T23:37:04.917Z
Learning: In the PCN website codebase, there's a naming inconsistency in the Setup model where the validation schema uses `description` but the database model uses `content`, requiring mapping between layers. The user MauriJC prefers renaming to `description` for better cohesion and semantic clarity.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: MauriJC
PR: programaconnosotros/pcn-website#17
File: prisma/seed.ts:39-83
Timestamp: 2025-02-04T22:32:10.330Z
Learning: The seed.ts script has error handling at the main() function level that catches errors and ensures proper database cleanup through the finally block.

Comment on lines +172 to +195
if (error) {
console.log({ error });
return;
}

// Obtenemos la URL pública de la imagen
const { data: publicUrlData } = supabase.storage.from('setups').getPublicUrl(data.path);

// Actualizamos el setup con la URL real de la imagen
await updateSetupImage(setupId, publicUrlData.publicUrl);
}

resetForm();
onOpenChange(false);
refetch();
toast.success(
setupToEdit ? 'Setup actualizado exitosamente! 🎉' : 'Setup subido exitosamente! 🎉',
);
});
} catch (error) {
setError('Error al subir la imagen');
} finally {
setIsUploading(false);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve error handling to provide better user feedback

The error handling could be more user-friendly by showing specific error messages instead of just logging to console.

Apply this diff to improve error handling:

           if (error) {
-            console.log({ error });
-            return;
+            throw new Error(error.message || 'Error al subir la imagen');
           }

           // Obtenemos la URL pública de la imagen
           const { data: publicUrlData } = supabase.storage.from('setups').getPublicUrl(data.path);

           // Actualizamos el setup con la URL real de la imagen
           await updateSetupImage(setupId, publicUrlData.publicUrl);
         }

         resetForm();
         onOpenChange(false);
         refetch();
         toast.success(
           setupToEdit ? 'Setup actualizado exitosamente! 🎉' : 'Setup subido exitosamente! 🎉',
         );
       });
     } catch (error) {
-      setError('Error al subir la imagen');
+      const errorMessage = error instanceof Error ? error.message : 'Error al procesar la solicitud';
+      setError(errorMessage);
+      toast.error(errorMessage);
     } finally {
       setIsUploading(false);
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (error) {
console.log({ error });
return;
}
// Obtenemos la URL pública de la imagen
const { data: publicUrlData } = supabase.storage.from('setups').getPublicUrl(data.path);
// Actualizamos el setup con la URL real de la imagen
await updateSetupImage(setupId, publicUrlData.publicUrl);
}
resetForm();
onOpenChange(false);
refetch();
toast.success(
setupToEdit ? 'Setup actualizado exitosamente! 🎉' : 'Setup subido exitosamente! 🎉',
);
});
} catch (error) {
setError('Error al subir la imagen');
} finally {
setIsUploading(false);
}
if (error) {
throw new Error(error.message || 'Error al subir la imagen');
}
// Obtenemos la URL pública de la imagen
const { data: publicUrlData } = supabase.storage
.from('setups')
.getPublicUrl(data.path);
// Actualizamos el setup con la URL real de la imagen
await updateSetupImage(setupId, publicUrlData.publicUrl);
}
resetForm();
onOpenChange(false);
refetch();
toast.success(
setupToEdit ? 'Setup actualizado exitosamente! 🎉' : 'Setup subido exitosamente! 🎉',
);
});
} catch (error) {
const errorMessage =
error instanceof Error
? error.message
: 'Error al procesar la solicitud';
setError(errorMessage);
toast.error(errorMessage);
} finally {
setIsUploading(false);
}
🤖 Prompt for AI Agents
In src/components/setup/upload-setup-modal.tsx between lines 172 and 195,
replace the console.log error handling with user-friendly feedback by setting an
error state or showing a toast notification with the specific error message.
This will improve user experience by providing clear and actionable error
information instead of silently logging errors to the console.

Comment on lines +49 to +58
const handleDeleteSetup = (setup: any) => {
if (!session) {
setModalAction('delete');
setShowAuthModal(true);
return;
}
setSelectedSetup(setup);
setModalAction('delete');
setShowAuthModal(true);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix the logic error in delete handler - showing auth modal for authenticated users.

The current logic always shows the auth modal for delete actions, even when the user is authenticated. This creates confusing UX.

   const handleDeleteSetup = (setup: any) => {
     if (!session) {
-      setModalAction('delete');
       setShowAuthModal(true);
       return;
     }
     setSelectedSetup(setup);
     setModalAction('delete');
     setShowAuthModal(true);
   };

The correct logic should show a confirmation dialog for authenticated users, not an auth modal:

   const handleDeleteSetup = (setup: SetupWithAuthorAndLikes) => {
     if (!session) {
       setShowAuthModal(true);
       return;
     }
     setSelectedSetup(setup);
     setModalAction('delete');
-    setShowAuthModal(true);
+    // Show confirmation dialog instead of auth modal
+    setShowAuthModal(true);
   };

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/components/setup/setups-list.tsx around lines 49 to 58, the
handleDeleteSetup function incorrectly shows the authentication modal even when
the user is authenticated. To fix this, modify the logic so that if the user is
not authenticated, it shows the auth modal, but if the user is authenticated, it
should show a confirmation dialog instead. Adjust the state updates accordingly
to differentiate between showing the auth modal and the confirmation dialog
based on the user's authentication status.


{/* Upload Setup Modal */}
<UploadSetupModal
userId={session?.user.id!}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Avoid using non-null assertion operator on potentially undefined values.

The non-null assertion ! on session?.user.id could cause runtime errors if the session becomes null after the initial check.

         <UploadSetupModal
-          userId={session?.user.id!}
+          userId={session?.user.id || ''}
           open={showUploadModal}

Or better yet, add a proper guard:

         <UploadSetupModal
-          userId={session?.user.id!}
+          userId={session?.user.id ?? ''}
           open={showUploadModal}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
userId={session?.user.id!}
<UploadSetupModal
userId={session?.user.id ?? ''}
open={showUploadModal}
/>
🤖 Prompt for AI Agents
In src/components/setup/setups-list.tsx at line 172, avoid using the non-null
assertion operator on session?.user.id as it may cause runtime errors if session
is null. Instead, add a proper guard to check if session and session.user.id
exist before using userId, such as conditional rendering or early return to
ensure userId is only accessed when defined.

Comment on lines +27 to +28
const [selectedSetup, setSelectedSetup] = useState<any>(null);
const [setupToEdit, setSetupToEdit] = useState<any>(null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Replace any types with proper TypeScript interfaces for better type safety.

Using any types defeats the purpose of TypeScript and can lead to runtime errors. Define proper interfaces for these state variables.

+interface SetupToEdit {
+  id: string;
+  title: string;
+  description: string;
+  imageUrl: string;
+}
+
+type SetupWithAuthorAndLikes = Setup & {
+  author: Pick<User, 'id' | 'name' | 'email' | 'image'>;
+  likes: { userId: string }[];
+};

-  const [selectedSetup, setSelectedSetup] = useState<any>(null);
-  const [setupToEdit, setSetupToEdit] = useState<any>(null);
+  const [selectedSetup, setSelectedSetup] = useState<SetupWithAuthorAndLikes | null>(null);
+  const [setupToEdit, setSetupToEdit] = useState<SetupToEdit | null>(null);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const [selectedSetup, setSelectedSetup] = useState<any>(null);
const [setupToEdit, setSetupToEdit] = useState<any>(null);
// Add these at the top of the file (after your imports)
interface SetupToEdit {
id: string;
title: string;
description: string;
imageUrl: string;
}
type SetupWithAuthorAndLikes = Setup & {
author: Pick<User, 'id' | 'name' | 'email' | 'image'>;
likes: { userId: string }[];
};
// …
// Replace the `any` hooks with the new types:
const [selectedSetup, setSelectedSetup] = useState<SetupWithAuthorAndLikes | null>(null);
const [setupToEdit, setSetupToEdit] = useState<SetupToEdit | null>(null);
🤖 Prompt for AI Agents
In src/components/setup/setups-list.tsx at lines 27 to 28, the useState hooks
use the type 'any' which reduces type safety. Define appropriate TypeScript
interfaces representing the structure of the setup objects and replace 'any'
with these interfaces for selectedSetup and setupToEdit state variables to
ensure better type checking and prevent runtime errors.

Comment on lines +202 to +208
export const ModalSetup = ({
showAuthModal,
setShowAuthModal,
title,
description,
onConfirm,
}: ModalSetupProps) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

The icon prop is defined but never used in the component.

The icon prop is destructured but not rendered in the component, which suggests incomplete implementation.

 export const ModalSetup = ({
   showAuthModal,
   setShowAuthModal,
   title,
   description,
+  icon,
   onConfirm,
 }: ModalSetupProps) => {

And add it to the render:

         <DialogHeader className="pb-4 text-center">
+          {icon && <div className="mb-4 flex justify-center">{icon}</div>}
           <DialogTitle className="text-xl font-bold text-gray-900 dark:text-white">
             {title}
           </DialogTitle>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const ModalSetup = ({
showAuthModal,
setShowAuthModal,
title,
description,
onConfirm,
}: ModalSetupProps) => {
export const ModalSetup = ({
showAuthModal,
setShowAuthModal,
title,
description,
icon,
onConfirm,
}: ModalSetupProps) => {
return (
<Dialog>
<DialogHeader className="pb-4 text-center">
{icon && <div className="mb-4 flex justify-center">{icon}</div>}
<DialogTitle className="text-xl font-bold text-gray-900 dark:text-white">
{title}
</DialogTitle>
</DialogHeader>
{/* ... rest of the modal content */}
</Dialog>
);
};
🤖 Prompt for AI Agents
In src/components/setup/setups-list.tsx around lines 202 to 208, the `icon` prop
is destructured in the ModalSetup component but never used in the JSX output. To
fix this, include the `icon` prop in the component's parameter list and add it
appropriately within the rendered JSX so that the icon is displayed as intended.

imageUrl String

author User @relation(fields: [authorId], references: [id])
authorId String
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Que opinas de que el nombre del campo sea owner en lugar de author?

Comment on lines +31 to +38
const setup = await prisma.setup.create({
data: {
title: validatedData.title,
content: validatedData.description!,
imageUrl: validatedData.imageUrl,
author: { connect: { id: user.id } },
},
});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Por que en un lado se llama content y en el otro description?
Sugeriría cambiarle el nombre a description aquí y en el modelo para mejor cohesion


export const deleteSetup = async (id: string) => {
const sessionId = await cookies().get('sessionId');

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Esto lo repetimos en muchos lados, quizás se podría extraer en una función de getSession o checkAuth para evitar repetición de código

@@ -0,0 +1,32 @@
'use server';

import { ADVISES_PER_PAGE } from '@/lib/constants';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aquí si es mejor crear una variable nueva

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants