Repository: dennis-adrian/glitter-nextjs
Pull request #199: Feat/dev 107 allow admins to update order status
Author: login: dennis-adrian
Created: 2025-05-20T06:09:46Z | Merged: 2025-05-20T06:12:57Z



<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **New Features**
  - Added the ability to accept or delete orders directly from the orders table.
  - Introduced confirmation modals for accepting and deleting orders, providing clear prompts and feedback.
  - Added status badges to display the current status of each order in the table.
  - Included an actions menu in the orders table for streamlined order management.

- **User Interface**
  - Enhanced the orders table with new columns for order status and actions.
  - Improved user experience with loading states and toast notifications for order actions.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/app/components/organisms/orders/accept-order-form.tsx b/app/components/organisms/orders/accept-order-form.tsx
new file mode 100644
index 00000000..feab834b
--- /dev/null
+++ b/app/components/organisms/orders/accept-order-form.tsx
@@ -0,0 +1,44 @@
+"use client";
+
+import { BaseOrder } from "@/app/lib/orders/definitions";
+import { useForm } from "react-hook-form";
+import { Form } from "@/components/ui/form";
+import SubmitButton from "@/app/components/simple-submit-button";
+import { acceptOrder } from "@/app/lib/orders/actions";
+import { toast } from "sonner";
+
+type AcceptOrderFormProps = {
+	order: BaseOrder;
+	onSuccess: () => void;
+};
+
+export default function AcceptOrderForm({
+	order,
+	onSuccess,
+}: AcceptOrderFormProps) {
+	const form = useForm();
+
+	const action: () => void = form.handleSubmit(async () => {
+		const result = await acceptOrder(order.id);
+		if (result.success) {
+			toast.success(result.message);
+			onSuccess();
+		} else {
+			toast.error(result.message);
+		}
+	});
+
+	return (
+		<Form {...form}>
+			<form className="w-full" onSubmit={action}>
+				<SubmitButton
+					disabled={form.formState.isSubmitting}
+					loading={form.formState.isSubmitting}
+					loadingLabel="Aceptando pedido..."
+				>
+					Aceptar Pedido
+				</SubmitButton>
+			</form>
+		</Form>
+	);
+}
diff --git a/app/components/organisms/orders/accept-order-modal.tsx b/app/components/organisms/orders/accept-order-modal.tsx
new file mode 100644
index 00000000..5e6b1051
--- /dev/null
+++ b/app/components/organisms/orders/accept-order-modal.tsx
@@ -0,0 +1,38 @@
+"use client";
+
+import { Modal } from "@/app/components/atoms/modal";
+import AcceptOrderForm from "@/app/components/organisms/orders/accept-order-form";
+import { BaseOrder } from "@/app/lib/orders/definitions";
+import { Button } from "@/components/ui/button";
+import { AlertCircleIcon } from "lucide-react";
+
+export default function AcceptOrderModal({
+	order,
+	open,
+	setOpen,
+}: {
+	order: BaseOrder;
+	open: boolean;
+	setOpen: (open: boolean) => void;
+}) {
+	return (
+		<Modal isOpen={open} onClose={() => setOpen(false)}>
+			<div className="flex flex-col items-center gap-3 text-center my-4">
+				<AlertCircleIcon size={48} className="text-amber-500" />
+				<div className="flex flex-col gap-2">
+					<p>¿Te gustaría aceptar este pedido?</p>
+				</div>
+				<div className="flex w-full gap-2">
+					<Button
+						className="w-full"
+						variant="outline"
+						onClick={() => setOpen(false)}
+					>
+						Cancelar
+					</Button>
+					<AcceptOrderForm order={order} onSuccess={() => setOpen(false)} />
+				</div>
+			</div>
+		</Modal>
+	);
+}
diff --git a/app/components/organisms/orders/delete-order-form.tsx b/app/components/organisms/orders/delete-order-form.tsx
new file mode 100644
index 00000000..6c6c7c40
--- /dev/null
+++ b/app/components/organisms/orders/delete-order-form.tsx
@@ -0,0 +1,40 @@
+import SubmitButton from "@/app/components/simple-submit-button";
+import { Form } from "@/app/components/ui/form";
+import { deleteOrder } from "@/app/lib/orders/actions";
+import { BaseOrder } from "@/app/lib/orders/definitions";
+import { useForm } from "react-hook-form";
+import { toast } from "sonner";
+
+export default function DeleteOrderForm({
+	order,
+	onSuccess,
+}: {
+	order: BaseOrder;
+	onSuccess: () => void;
+}) {
+	const form = useForm();
+
+	const action: () => void = form.handleSubmit(async () => {
+		const result = await deleteOrder(order.id);
+		if (result.success) {
+			toast.success(result.message);
+			onSuccess();
+		} else {
+			toast.error(result.message);
+		}
+	});
+
+	return (
+		<Form {...form}>
+			<form className="w-full" onSubmit={action}>
+				<SubmitButton
+					disabled={form.formState.isSubmitting}
+					loading={form.formState.isSubmitting}
+					loadingLabel="Eliminando..."
+				>
+					Eliminar
+				</SubmitButton>
+			</form>
+		</Form>
+	);
+}
diff --git a/app/components/organisms/orders/delete-order-modal.tsx b/app/components/organisms/orders/delete-order-modal.tsx
new file mode 100644
index 00000000..3629fe7c
--- /dev/null
+++ b/app/components/organisms/orders/delete-order-modal.tsx
@@ -0,0 +1,37 @@
+import { Modal } from "@/app/components/atoms/modal";
+import DeleteOrderForm from "@/app/components/organisms/orders/delete-order-form";
+import { Button } from "@/app/components/ui/button";
+import { BaseOrder } from "@/app/lib/orders/definitions";
+import { AlertCircleIcon } from "lucide-react";
+
+export default function DeleteOrderModal({
+	order,
+	open,
+	setOpen,
+}: {
+	order: BaseOrder;
+	open: boolean;
+	setOpen: (open: boolean) => void;
+}) {
+	return (
+		<Modal isOpen={open} onClose={() => setOpen(false)}>
+			<div className="flex items-center flex-col gap-6 m-auto text-center py-4">
+				<AlertCircleIcon size={48} className="text-red-500" />
+				<div className="flex flex-col gap-2">
+					<p>¿Estás seguro que deseas eliminar este pedido ?</p>
+					<p>La acción no se puede deshacer.</p>
+				</div>
+			</div>
+			<div className="flex w-full gap-2">
+				<Button
+					className="w-full"
+					variant="outline"
+					onClick={() => setOpen(false)}
+				>
+					Cancelar
+				</Button>
+				<DeleteOrderForm order={order} onSuccess={() => setOpen(false)} />
+			</div>
+		</Modal>
+	);
+}
diff --git a/app/components/organisms/orders/table-actions-cell.tsx b/app/components/organisms/orders/table-actions-cell.tsx
new file mode 100644
index 00000000..b94c5aa7
--- /dev/null
+++ b/app/components/organisms/orders/table-actions-cell.tsx
@@ -0,0 +1,57 @@
+"use client";
+
+import { CheckCircleIcon, MoreHorizontalIcon, Trash2Icon } from "lucide-react";
+
+import { Button } from "@/app/components/ui/button";
+import {
+	DropdownMenu,
+	DropdownMenuContent,
+	DropdownMenuItem,
+	DropdownMenuLabel,
+	DropdownMenuSeparator,
+	DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
+import { OrderWithRelations } from "@/app/lib/orders/definitions";
+import { useState } from "react";
+import AcceptOrderModal from "@/app/components/organisms/orders/accept-order-modal";
+import DeleteOrderModal from "@/app/components/organisms/orders/delete-order-modal";
+
+export function OrdersActionsCell({ order }: { order: OrderWithRelations }) {
+	const [openAcceptModal, setOpenAcceptModal] = useState(false);
+	const [openDeleteModal, setOpenDeleteModal] = useState(false);
+
+	return (
+		<>
+			<DropdownMenu>
+				<DropdownMenuTrigger asChild>
+					<Button variant="ghost" className="h-8 w-8 p-0">
+						<span className="sr-only">Open menu</span>
+						<MoreHorizontalIcon className="h-4 w-4" />
+					</Button>
+				</DropdownMenuTrigger>
+				<DropdownMenuContent align="end">
+					<DropdownMenuLabel>Acciones</DropdownMenuLabel>
+					<DropdownMenuSeparator />
+					<DropdownMenuItem onClick={() => setOpenAcceptModal(true)}>
+						<CheckCircleIcon className="h-4 w-4 mr-1" />
+						Aceptar Pedido
+					</DropdownMenuItem>
+					<DropdownMenuItem onClick={() => setOpenDeleteModal(true)}>
+						<Trash2Icon className="h-4 w-4 mr-1" />
+						Eliminar
+					</DropdownMenuItem>
+				</DropdownMenuContent>
+			</DropdownMenu>
+			<AcceptOrderModal
+				order={order}
+				open={openAcceptModal}
+				setOpen={setOpenAcceptModal}
+			/>
+			<DeleteOrderModal
+				order={order}
+				open={openDeleteModal}
+				setOpen={setOpenDeleteModal}
+			/>
+		</>
+	);
+}
diff --git a/app/components/organisms/orders/table-columns.tsx b/app/components/organisms/orders/table-columns.tsx
index 08277267..b1abf170 100644
--- a/app/components/organisms/orders/table-columns.tsx
+++ b/app/components/organisms/orders/table-columns.tsx
@@ -1,3 +1,5 @@
+import OrderStatusBadge from "@/app/components/atoms/order-status-badge";
+import { OrdersActionsCell } from "@/app/components/organisms/orders/table-actions-cell";
 import { DataTableColumnHeader } from "@/app/components/ui/data_table/column-header";
 import ProfileQuickViewInfo from "@/app/components/users/profile-quick-view-info";
 import { formatDate } from "@/app/lib/formatters";
@@ -10,6 +12,7 @@ export const columnTitles = {
 	customer: "Cliente",
 	createdAt: "Fecha de creación",
 	items: "Artículos",
+	status: "Estado",
 	total: "Total",
 };
 
@@ -61,6 +64,15 @@ export const columns: ColumnDef<OrderWithRelations>[] = [
 			);
 		},
 	},
+	{
+		accessorKey: "status",
+		header: ({ column }) => (
+			<DataTableColumnHeader column={column} title={columnTitles.status} />
+		),
+		cell: ({ row }) => {
+			return <OrderStatusBadge status={row.original.status} />;
+		},
+	},
 	{
 		accessorKey: "createdAt",
 		header: ({ column }) => (
@@ -76,4 +88,13 @@ export const columns: ColumnDef<OrderWithRelations>[] = [
 			);
 		},
 	},
+	{
+		accessorKey: "actions",
+		header: ({ column }) => <DataTableColumnHeader column={column} title="" />,
+		cell: ({ row }) => {
+			return <OrdersActionsCell order={row.original} />;
+		},
+		enableSorting: false,
+		enableHiding: false,
+	},
 ];
diff --git a/app/lib/orders/actions.ts b/app/lib/orders/actions.ts
index 49e210c7..f767a92e 100644
--- a/app/lib/orders/actions.ts
+++ b/app/lib/orders/actions.ts
@@ -4,6 +4,7 @@ import { orderItems, orders } from "@/db/schema";
 import { NewOrderItem, OrderWithRelations } from "@/app/lib/orders/definitions";
 import { db } from "@/db";
 import { eq } from "drizzle-orm";
+import { revalidatePath } from "next/cache";
 
 export async function createOrder(
 	orderItemsToInsert: NewOrderItem[],
@@ -141,3 +142,42 @@ export async function fetchOrders() {
 		return [];
 	}
 }
+
+export async function acceptOrder(orderId: number) {
+	try {
+		await db
+			.update(orders)
+			.set({ status: "processing" })
+			.where(eq(orders.id, orderId));
+	} catch (error) {
+		console.error(error);
+		return {
+			success: false,
+			message: "No se pudo aceptar la orden.",
+		};
+	}
+
+	revalidatePath("/dashboard/orders");
+	return {
+		success: true,
+		message: "Orden aceptada correctamente.",
+	};
+}
+
+export async function deleteOrder(orderId: number) {
+	try {
+		await db.delete(orders).where(eq(orders.id, orderId));
+	} catch (error) {
+		console.error(error);
+		return {
+			success: false,
+			message: "No se pudo eliminar la orden.",
+		};
+	}
+
+	revalidatePath("/dashboard/orders");
+	return {
+		success: true,
+		message: "Orden eliminada correctamente.",
+	};
+}


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 3**

<details>
<summary>🧹 Nitpick comments (5)</summary><blockquote>

<details>
<summary>app/components/organisms/orders/delete-order-form.tsx (1)</summary><blockquote>

`8-26`: **Consider adding error type information**

The error handling in the form only displays the message but doesn't distinguish between different types of errors. Consider extending the error handling to provide more specific feedback based on the error type.


```diff
export default function DeleteOrderForm({
	order,
	onSuccess,
}: {
	order: BaseOrder;
	onSuccess: () => void;
}) {
	const form = useForm();

	const action: () => void = form.handleSubmit(async () => {
		const result = await deleteOrder(order.id);
		if (result.success) {
			toast.success(result.message);
			onSuccess();
		} else {
-			toast.error(result.message);
+			toast.error(result.message, {
+				description: "Intente de nuevo más tarde o contacte a soporte.",
+			});
		}
	});
```

</blockquote></details>
<details>
<summary>app/components/organisms/orders/accept-order-form.tsx (1)</summary><blockquote>

`15-29`: **Consider adding detailed error handling**

Similar to the delete form, the error handling could be improved to provide more context to the user.


```diff
	const action: () => void = form.handleSubmit(async () => {
		const result = await acceptOrder(order.id);
		if (result.success) {
			toast.success(result.message);
			onSuccess();
		} else {
-			toast.error(result.message);
+			toast.error(result.message, {
+				description: "Intente de nuevo más tarde o contacte a soporte.",
+			});
		}
	});
```

</blockquote></details>
<details>
<summary>app/components/organisms/orders/delete-order-modal.tsx (2)</summary><blockquote>

`16-24`: **Fix Spanish punctuation**

In Spanish, there should be no space before the question mark.


```diff
				<div className="flex flex-col gap-2">
-					<p>¿Estás seguro que deseas eliminar este pedido ?</p>
+					<p>¿Estás seguro que deseas eliminar este pedido?</p>
					<p>La acción no se puede deshacer.</p>
				</div>
```

---

`25-34`: **Consider showing order details in the modal**

The modal doesn't display any information about which order is being deleted. Consider adding some order details (like ID, date, or total amount) to help users confirm they're deleting the correct order.


```diff
			<div className="flex items-center flex-col gap-6 m-auto text-center py-4">
				<AlertCircleIcon size={48} className="text-red-500" />
				<div className="flex flex-col gap-2">
					<p>¿Estás seguro que deseas eliminar este pedido?</p>
+					<p className="font-medium">Orden #{order.id} - {new Date(order.orderDate).toLocaleDateString()}</p>
+					<p className="font-medium">Total: ${order.totalAmount.toFixed(2)}</p>
					<p>La acción no se puede deshacer.</p>
				</div>
			</div>
```

</blockquote></details>
<details>
<summary>app/components/organisms/orders/accept-order-modal.tsx (1)</summary><blockquote>

`9-38`: **Well-structured modal component with clear user flow.**

The `AcceptOrderModal` component is well-organized with appropriate spacing, clear user options, and good visual cues. It effectively separates concerns by using `AcceptOrderForm` for the actual acceptance logic.



Consider displaying some order-specific details in the confirmation message to provide more context to the admin. For example:

```diff
 <div className="flex flex-col gap-2">
-	<p>¿Te gustaría aceptar este pedido?</p>
+	<p>¿Te gustaría aceptar este pedido #{order.id}?</p>
+	<p className="text-sm text-muted-foreground">Cliente: {order.customer?.name || 'Cliente'}</p>
 </div>
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**
**Cache: Disabled due to data retention organization setting**
**Knowledge Base: Disabled due to data retention organization setting**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 30928fb7b955fce2df3b8b9791c7fee20a362913 and 8691aee15d8ff139e7288ff97c0f71051cbc0aae.

</details>

<details>
<summary>📒 Files selected for processing (7)</summary>

* `app/components/organisms/orders/accept-order-form.tsx` (1 hunks)
* `app/components/organisms/orders/accept-order-modal.tsx` (1 hunks)
* `app/components/organisms/orders/delete-order-form.tsx` (1 hunks)
* `app/components/organisms/orders/delete-order-modal.tsx` (1 hunks)
* `app/components/organisms/orders/table-actions-cell.tsx` (1 hunks)
* `app/components/organisms/orders/table-columns.tsx` (4 hunks)
* `app/lib/orders/actions.ts` (2 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (3)</summary>

<details>
<summary>app/lib/orders/actions.ts (2)</summary><blockquote>

<details>
<summary>db/index.ts (1)</summary>

* `db` (11-11)

</details>
<details>
<summary>db/schema.ts (1)</summary>

* `orders` (845-855)

</details>

</blockquote></details>
<details>
<summary>app/components/organisms/orders/delete-order-form.tsx (3)</summary><blockquote>

<details>
<summary>app/lib/orders/definitions.ts (1)</summary>

* `BaseOrder` (11-11)

</details>
<details>
<summary>app/lib/orders/actions.ts (1)</summary>

* `deleteOrder` (167-183)

</details>
<details>
<summary>app/components/simple-submit-button.tsx (1)</summary>

* `SubmitButton` (16-34)

</details>

</blockquote></details>
<details>
<summary>app/components/organisms/orders/accept-order-form.tsx (4)</summary><blockquote>

<details>
<summary>app/lib/orders/definitions.ts (1)</summary>

* `BaseOrder` (11-11)

</details>
<details>
<summary>app/lib/orders/actions.ts (1)</summary>

* `acceptOrder` (146-165)

</details>
<details>
<summary>app/components/ui/form.tsx (1)</summary>

* `Form` (173-173)

</details>
<details>
<summary>app/components/simple-submit-button.tsx (1)</summary>

* `SubmitButton` (16-34)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>🔇 Additional comments (9)</summary><blockquote>

<details>
<summary>app/components/organisms/orders/delete-order-form.tsx (1)</summary>

`29-38`: **LGTM! Form implementation looks good**

The form implementation is clean and well-structured, with good handling of the loading state during submission.

</details>
<details>
<summary>app/components/organisms/orders/accept-order-form.tsx (4)</summary>

`1-2`: **Correctly marked as client component**

Good use of the "use client" directive for this interactive component that uses client-side hooks and event handling.

---

`3-9`: **LGTM! Good import organization**

The imports are well-organized and properly separated by functionality.

---

`10-14`: **Good type definition**

Clear and concise TypeScript interface for the component props.

---

`31-43`: **LGTM! Good form implementation**

The form implementation is clean with appropriate loading states and disabled submission during processing.

</details>
<details>
<summary>app/components/organisms/orders/delete-order-modal.tsx (1)</summary>

`7-15`: **Good modal component structure**

The component props are well-defined with clear types.

</details>
<details>
<summary>app/components/organisms/orders/table-columns.tsx (3)</summary>

`1-2`: **LGTM! Appropriate imports for new table features.**

The imports for `OrderStatusBadge` and `OrdersActionsCell` are properly added to support the new table columns.



Also applies to: 15-15

---

`91-99`: **Actions column properly implemented with appropriate configuration.**

The actions column is correctly implemented and properly configured with sorting and hiding disabled, which is appropriate for action buttons.

---

`67-75`: _💡 Verification agent_

<details>
<summary>🧩 Analysis chain</summary>

**Status column implementation follows consistent pattern.**

The Status column is well-implemented, following the same pattern as other columns in the table.


---

🏁 Script executed:

```shell
#!/bin/bash
# Verify that OrderStatusBadge can handle all possible order status values
# Let's check what statuses are defined in the codebase

# First, let's check if there's a type definition for order status
rg -A 5 "type.*Status|enum.*Status" --glob "**/*.ts*"

# Then, check if OrderStatusBadge handles all those status values
rg -A 15 "OrderStatusBadge" --glob "**/*.tsx"
```

Length of output: 9791

---

🏁 Script executed:

```shell
#!/bin/bash
# Show BaseOrder type definition context
echo "=== BaseOrder definition context ==="
rg -A 10 "BaseOrder" -n app/lib/orders/definitions.ts

# Check for orderStatusEnum if exists
echo "=== orderStatusEnum references ==="
rg -A 5 "orderStatusEnum" -n app/lib/orders/definitions.ts

# List all handled cases in OrderStatusBadge
echo "=== Handled status cases in OrderStatusBadge ==="
rg -n "case" app/components/atoms/order-status-badge.tsx
```

Length of output: 1258

---

🏁 Script executed:

```shell
#!/bin/bash
# List schema files to locate orderStatusEnum definition
echo "=== Schema files ==="
fd --type f --glob "*schema*.ts"

# Find orderStatusEnum definition
echo "=== orderStatusEnum definition ==="
rg -n "orderStatusEnum\s*=" -n .
```

Length of output: 287

---

🏁 Script executed:

```shell
#!/bin/bash
# Extract the full list of statuses from the orderStatusEnum definition
rg -A 20 'export const orderStatusEnum' -n db/schema.ts
```

Length of output: 962

---



</details>

**Add missing “paid” case to OrderStatusBadge**

The `orderStatusEnum` in `db/schema.ts` defines five statuses—`pending`, `processing`, **`paid`**, `delivered`, and `cancelled`—but `OrderStatusBadge` only handles four. As a result, orders with status `paid` will render nothing.

Please update `app/components/atoms/order-status-badge.tsx` to include a `case "paid":` branch (or a default) so that “paid” orders display a badge. For example:

```diff
 switch (status) {
   case "pending":
     return (…);
   case "processing":
     return (…);
+  case "paid":
+    return (
+      <Badge
+        variant="outline"
+        className="text-blue-600 border-blue-200 bg-blue-50 gap-1"
+      >
+        {statusLabel}
+      </Badge>
+    );
   case "delivered":
     return (…);
   case "cancelled":
     return (…);
+  default:
+    return <Badge>{statusLabel}</Badge>;
 }
```

- File: app/components/atoms/order-status-badge.tsx  
- Missing handling for `"paid"` status.  




> Likely an incorrect or invalid review comment.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-20T06:14:08Z

Review comments:
diff_hunk: @@ -141,3 +142,42 @@ export async function fetchOrders() {
 		return [];
 	}
 }
+
+export async function acceptOrder(orderId: number) {
+	try {
+		await db
+			.update(orders)
+			.set({ status: "processing" })
+			.where(eq(orders.id, orderId));
+	} catch (error) {
+		console.error(error);
+		return {
+			success: false,
+			message: "No se pudo aceptar la orden.",
+		};
+	}
+
+	revalidatePath("/dashboard/orders");
+	return {
+		success: true,
+		message: "Orden aceptada correctamente.",
+	};
+}
+
+export async function deleteOrder(orderId: number) {
+	try {
+		await db.delete(orders).where(eq(orders.id, orderId));
+	} catch (error) {
+		console.error(error);
+		return {
+			success: false,
+			message: "No se pudo eliminar la orden.",
+		};
+	}
+
+	revalidatePath("/dashboard/orders");
+	return {
+		success: true,
+		message: "Orden eliminada correctamente.",
+	};
+}
path: app/lib/orders/actions.ts
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Verify order existence before deletion**

Similar to the `acceptOrder` function, the `deleteOrder` function should first check if the order exists before attempting to delete it.


```diff
export async function deleteOrder(orderId: number) {
	try {
+		// Check if order exists first
+		const orderExists = await db.query.orders.findFirst({
+			where: eq(orders.id, orderId),
+		});
+		
+		if (!orderExists) {
+			return {
+				success: false,
+				message: "La orden no existe.",
+			};
+		}
+
		await db.delete(orders).where(eq(orders.id, orderId));
	} catch (error) {
		console.error(error);
		return {
			success: false,
			message: "No se pudo eliminar la orden.",
		};
	}

	revalidatePath("/dashboard/orders");
	return {
		success: true,
		message: "Orden eliminada correctamente.",
	};
}
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **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.

```suggestion
export async function deleteOrder(orderId: number) {
	try {
		// Check if order exists first
		const orderExists = await db.query.orders.findFirst({
			where: eq(orders.id, orderId),
		});

		if (!orderExists) {
			return {
				success: false,
				message: "La orden no existe.",
			};
		}

		await db.delete(orders).where(eq(orders.id, orderId));
	} catch (error) {
		console.error(error);
		return {
			success: false,
			message: "No se pudo eliminar la orden.",
		};
	}

	revalidatePath("/dashboard/orders");
	return {
		success: true,
		message: "Orden eliminada correctamente.",
	};
}
```

</details>

<!-- suggestion_end -->

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In app/lib/orders/actions.ts around lines 167 to 183, the deleteOrder function
should first verify if the order with the given orderId exists before attempting
deletion. To fix this, add a query to check for the order's existence using the
orderId; if the order does not exist, return an appropriate failure response
without attempting deletion. Only proceed with the deletion if the order is
found.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-20T06:14:07Z
author_association: NONE
diff_hunk: @@ -141,3 +142,42 @@ export async function fetchOrders() {
 		return [];
 	}
 }
+
+export async function acceptOrder(orderId: number) {
+	try {
+		await db
+			.update(orders)
+			.set({ status: "processing" })
+			.where(eq(orders.id, orderId));
+	} catch (error) {
+		console.error(error);
+		return {
+			success: false,
+			message: "No se pudo aceptar la orden.",
+		};
+	}
+
+	revalidatePath("/dashboard/orders");
+	return {
+		success: true,
+		message: "Orden aceptada correctamente.",
+	};
+}
path: app/lib/orders/actions.ts
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Verify order existence before accepting**

The `acceptOrder` function updates an order's status without checking if the order exists first. Consider adding a validation step to ensure the order exists before trying to update it.


```diff
export async function acceptOrder(orderId: number) {
	try {
+		// Check if order exists first
+		const orderExists = await db.query.orders.findFirst({
+			where: eq(orders.id, orderId),
+		});
+		
+		if (!orderExists) {
+			return {
+				success: false,
+				message: "La orden no existe.",
+			};
+		}
+		
		await db
			.update(orders)
			.set({ status: "processing" })
			.where(eq(orders.id, orderId));
	} catch (error) {
		console.error(error);
		return {
			success: false,
			message: "No se pudo aceptar la orden.",
		};
	}

	revalidatePath("/dashboard/orders");
	return {
		success: true,
		message: "Orden aceptada correctamente.",
	};
}
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **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.

```suggestion
export async function acceptOrder(orderId: number) {
	try {
		// Check if order exists first
		const orderExists = await db.query.orders.findFirst({
			where: eq(orders.id, orderId),
		});

		if (!orderExists) {
			return {
				success: false,
				message: "La orden no existe.",
			};
		}

		await db
			.update(orders)
			.set({ status: "processing" })
			.where(eq(orders.id, orderId));
	} catch (error) {
		console.error(error);
		return {
			success: false,
			message: "No se pudo aceptar la orden.",
		};
	}

	revalidatePath("/dashboard/orders");
	return {
		success: true,
		message: "Orden aceptada correctamente.",
	};
}
```

</details>

<!-- suggestion_end -->

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In app/lib/orders/actions.ts around lines 146 to 165, the acceptOrder function
updates the order status without verifying if the order exists. Add a validation
step before the update by querying the database to check if an order with the
given orderId exists. If it does not exist, return a failure response indicating
the order was not found. Only proceed with the update if the order is confirmed
to exist.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-20T06:14:08Z
author_association: NONE
diff_hunk: @@ -0,0 +1,57 @@
+"use client";
+
+import { CheckCircleIcon, MoreHorizontalIcon, Trash2Icon } from "lucide-react";
+
+import { Button } from "@/app/components/ui/button";
+import {
+	DropdownMenu,
+	DropdownMenuContent,
+	DropdownMenuItem,
+	DropdownMenuLabel,
+	DropdownMenuSeparator,
+	DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
+import { OrderWithRelations } from "@/app/lib/orders/definitions";
+import { useState } from "react";
+import AcceptOrderModal from "@/app/components/organisms/orders/accept-order-modal";
+import DeleteOrderModal from "@/app/components/organisms/orders/delete-order-modal";
+
+export function OrdersActionsCell({ order }: { order: OrderWithRelations }) {
+	const [openAcceptModal, setOpenAcceptModal] = useState(false);
+	const [openDeleteModal, setOpenDeleteModal] = useState(false);
+
+	return (
+		<>
+			<DropdownMenu>
+				<DropdownMenuTrigger asChild>
+					<Button variant="ghost" className="h-8 w-8 p-0">
+						<span className="sr-only">Open menu</span>
+						<MoreHorizontalIcon className="h-4 w-4" />
+					</Button>
+				</DropdownMenuTrigger>
+				<DropdownMenuContent align="end">
+					<DropdownMenuLabel>Acciones</DropdownMenuLabel>
+					<DropdownMenuSeparator />
+					<DropdownMenuItem onClick={() => setOpenAcceptModal(true)}>
+						<CheckCircleIcon className="h-4 w-4 mr-1" />
+						Aceptar Pedido
+					</DropdownMenuItem>
+					<DropdownMenuItem onClick={() => setOpenDeleteModal(true)}>
+						<Trash2Icon className="h-4 w-4 mr-1" />
+						Eliminar
+					</DropdownMenuItem>
+				</DropdownMenuContent>
+			</DropdownMenu>
+			<AcceptOrderModal
+				order={order}
+				open={openAcceptModal}
+				setOpen={setOpenAcceptModal}
+			/>
+			<DeleteOrderModal
+				order={order}
+				open={openDeleteModal}
+				setOpen={setOpenDeleteModal}
+			/>
+		</>
+	);
+}
path: app/components/organisms/orders/table-actions-cell.tsx
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Well-implemented actions cell with dropdown menu and modals.**

The component provides a clean UI for order actions using a dropdown menu and confirmation modals for important actions.



The current implementation shows all actions regardless of the order's status. Consider conditionally showing or disabling actions based on the current order status:

```diff
<DropdownMenuItem 
+   disabled={order.status !== 'pending'}
    onClick={() => setOpenAcceptModal(true)}
>
    <CheckCircleIcon className="h-4 w-4 mr-1" />
    Aceptar Pedido
</DropdownMenuItem>
```


Consider adding a visual distinction for the destructive "Delete" action to warn users:

```diff
<DropdownMenuItem 
    onClick={() => setOpenDeleteModal(true)}
+   className="text-destructive focus:text-destructive"
>
    <Trash2Icon className="h-4 w-4 mr-1" />
    Eliminar
</DropdownMenuItem>
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **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.

```suggestion
export function OrdersActionsCell({ order }: { order: OrderWithRelations }) {
	const [openAcceptModal, setOpenAcceptModal] = useState(false);
	const [openDeleteModal, setOpenDeleteModal] = useState(false);

	return (
		<>
			<DropdownMenu>
				<DropdownMenuTrigger asChild>
					<Button variant="ghost" className="h-8 w-8 p-0">
						<span className="sr-only">Open menu</span>
						<MoreHorizontalIcon className="h-4 w-4" />
					</Button>
				</DropdownMenuTrigger>
				<DropdownMenuContent align="end">
					<DropdownMenuLabel>Acciones</DropdownMenuLabel>
					<DropdownMenuSeparator />
					<DropdownMenuItem
						disabled={order.status !== 'pending'}
						onClick={() => setOpenAcceptModal(true)}
					>
						<CheckCircleIcon className="h-4 w-4 mr-1" />
						Aceptar Pedido
					</DropdownMenuItem>
					<DropdownMenuItem
						onClick={() => setOpenDeleteModal(true)}
						className="text-destructive focus:text-destructive"
					>
						<Trash2Icon className="h-4 w-4 mr-1" />
						Eliminar
					</DropdownMenuItem>
				</DropdownMenuContent>
			</DropdownMenu>
			<AcceptOrderModal
				order={order}
				open={openAcceptModal}
				setOpen={setOpenAcceptModal}
			/>
			<DeleteOrderModal
				order={order}
				open={openDeleteModal}
				setOpen={setOpenDeleteModal}
			/>
		</>
	);
}
```

</details>

<!-- suggestion_end -->

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In app/components/organisms/orders/table-actions-cell.tsx around lines 19 to 57,
the dropdown menu currently shows all actions regardless of the order's status
and lacks a visual distinction for the destructive "Delete" action. Update the
component to conditionally render or disable the "Aceptar Pedido" and "Eliminar"
actions based on the order's status to prevent invalid operations. Additionally,
apply a visual style (such as a red color or a "destructive" variant) to the
"Eliminar" DropdownMenuItem to clearly indicate it is a destructive action and
warn users.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-20T06:14:08Z
author_association: NONE

PR comments:
user: login: vercel[bot]
created_at: 2025-05-20T06:09:51Z
body: [vc]: #AZcgkDkIE/gN6jT/dSoSJmgIllI1g7hUZ9Bf6oKvI5Q=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJnbGl0dGVyLW5leHRqcyIsImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS9nbGl0dGVyLTg4MjRkNGI1L2dsaXR0ZXItbmV4dGpzLzlGMUNGWEpjWkw0Um01N0JEdFNEdVZaMmMxTGQiLCJwcmV2aWV3VXJsIjoiZ2xpdHRlci1uZXh0anMtZ2l0LWZlYXQtZGV2LTEwNy1hbGxvdy1hLTY5MTNhNC1nbGl0dGVyLTg4MjRkNGI1LnZlcmNlbC5hcHAiLCJuZXh0Q29tbWl0U3RhdHVzIjoiREVQTE9ZRUQiLCJsaXZlRmVlZGJhY2siOnsicmVzb2x2ZWQiOjAsInVucmVzb2x2ZWQiOjAsInRvdGFsIjowLCJsaW5rIjoiZ2xpdHRlci1uZXh0anMtZ2l0LWZlYXQtZGV2LTEwNy1hbGxvdy1hLTY5MTNhNC1nbGl0dGVyLTg4MjRkNGI1LnZlcmNlbC5hcHAifSwicm9vdERpcmVjdG9yeSI6bnVsbH1dfQ==
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **glitter-nextjs** | ✅ Ready ([Inspect](https://vercel.com/glitter-8824d4b5/glitter-nextjs/9F1CFXJcZL4Rm57BDtSDuVZ2c1Ld)) | [Visit Preview](https://glitter-nextjs-git-feat-dev-107-allow-a-6913a4-glitter-8824d4b5.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/glitter-nextjs-git-feat-dev-107-allow-a-6913a4-glitter-8824d4b5.vercel.app?via=pr-comment-feedback-link) | May 20, 2025 6:11am |


author_association: CONTRIBUTOR
user: login: coderabbitai[bot]
created_at: 2025-05-20T06:09:52Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough

This update introduces new React components and supporting backend actions to enable accepting and deleting orders within a dashboard. It adds modal dialogs and forms for user confirmation and feedback, integrates toast notifications, and updates the orders table to include status and actions columns. Backend logic for order acceptance and deletion is implemented with cache revalidation.

## Changes

| File(s)                                                                                 | Change Summary                                                                                                              |
|-----------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------|
| app/components/organisms/orders/accept-order-form.tsx                                   | Added `AcceptOrderForm` React component for handling order acceptance with form state, async action, and toast feedback.   |
| app/components/organisms/orders/accept-order-modal.tsx                                  | Added `AcceptOrderModal` component to display a confirmation modal for accepting an order, using `AcceptOrderForm`.        |
| app/components/organisms/orders/delete-order-form.tsx                                   | Added `DeleteOrderForm` React component for handling order deletion with form state, async action, and toast feedback.     |
| app/components/organisms/orders/delete-order-modal.tsx                                  | Added `DeleteOrderModal` component to display a confirmation modal for deleting an order, using `DeleteOrderForm`.         |
| app/components/organisms/orders/table-actions-cell.tsx                                  | Added `OrdersActionsCell` component with dropdown menu and modals for accepting or deleting an order.                      |
| app/components/organisms/orders/table-columns.tsx                                       | Added "status" and "actions" columns to the orders table, using new badge and actions cell components.                     |
| app/lib/orders/actions.ts                                                               | Added async functions `acceptOrder` and `deleteOrder` for updating order status and deleting orders, with cache revalidation.|

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant User
    participant OrdersTable
    participant OrdersActionsCell
    participant AcceptOrderModal
    participant AcceptOrderForm
    participant Backend

    User->>OrdersTable: Views orders list
    OrdersTable->>OrdersActionsCell: Renders actions dropdown for each order
    User->>OrdersActionsCell: Clicks "Aceptar Pedido"
    OrdersActionsCell->>AcceptOrderModal: Opens accept modal
    User->>AcceptOrderForm: Submits accept form
    AcceptOrderForm->>Backend: Calls acceptOrder(orderId)
    Backend-->>AcceptOrderForm: Returns success/error
    AcceptOrderForm->>AcceptOrderModal: Triggers onSuccess (closes modal)
    AcceptOrderForm->>User: Shows toast notification
```

```mermaid
sequenceDiagram
    participant User
    participant OrdersTable
    participant OrdersActionsCell
    participant DeleteOrderModal
    participant DeleteOrderForm
    participant Backend

    User->>OrdersTable: Views orders list
    OrdersTable->>OrdersActionsCell: Renders actions dropdown for each order
    User->>OrdersActionsCell: Clicks "Eliminar"
    OrdersActionsCell->>DeleteOrderModal: Opens delete modal
    User->>DeleteOrderForm: Submits delete form
    DeleteOrderForm->>Backend: Calls deleteOrder(orderId)
    Backend-->>DeleteOrderForm: Returns success/error
    DeleteOrderForm->>DeleteOrderModal: Triggers onSuccess (closes modal)
    DeleteOrderForm->>User: Shows toast notification
```

## Poem

> 🥕  
> Orders now can come and go,  
> With modals bright and actions aglow.  
> Accept or delete—just click and see,  
> Toasts will cheer you, error-free!  
> Rabbits love a tidy list,  
> With every order checked (and none missed)!  
> 🐇✨

<!-- walkthrough_end -->
<!-- This is an auto-generated comment: all tool run failures by coderabbit.ai -->

> [!WARNING]
> There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.
> 
> <details>
> <summary>🔧 ESLint</summary>
> 
> > If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.
> 
> npm warn config production Use `--omit=dev` instead.
> npm warn ERESOLVE overriding peer dependency
> npm warn While resolving: @typescript-eslint/eslint-plugin@8.20.0
> npm warn Found: eslint@8.56.0
> npm warn node_modules/eslint
> npm warn   dev eslint@"^8" from the root project
> npm warn   7 more (@eslint-community/eslint-utils, eslint-config-next, ...)
> npm warn
> npm warn Could not resolve dependency:
> npm warn peer eslint@"^8.57.0 || ^9.0.0" from @typescript-eslint/eslint-plugin@8.20.0
> npm warn node_modules/eslint-config-next/node_modules/@typescript-eslint/eslint-plugin
> npm warn   @typescript-eslint/eslint-plugin@"^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0" from eslint-config-next@15.1.5
> npm warn   node_modules/eslint-config-next
> npm warn
> npm warn Conflicting peer dependency: eslint@9.27.0
> npm warn node_modules/eslint
> npm warn   peer eslint@"^8.57.0 || ^9.0.0" from @typescript-eslint/eslint-plugin@8.20.0
> npm warn   node_modules/eslint-config-next/node_modules/@typescript-eslint/eslint-plugin
> npm warn     @typescript-eslint/eslint-plugin@"^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0" from eslint-config-next@15.1.5
> npm warn     node_modules/eslint-config-next
> npm warn ERESOLVE overriding peer dependency
> npm warn While resolving: @typescript-eslint/parser@8.20.0
> npm warn Found: eslint@8.56.0
> npm warn node_modules/eslint
> npm warn   dev eslint@"^8" from the root project
> npm warn   7 more (@eslint-community/eslint-utils, eslint-config-next, ...)
> npm warn
> npm warn Could not resolve dependency:
> npm warn peer eslint@"^8.57.0 || ^9.0.0" from @typescript-eslint/parser@8.20.0
> npm warn node_modules/eslint-config-next/node_modules/@typescript-eslint/parser
> npm warn   @typescript-eslint/parser@"^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0" from eslint-config-next@15.1.5
> npm warn   node_modules/eslint-config-next
> npm warn   1 more (@typescript-eslint/eslint-plugin)
> npm warn
> npm warn Conflicting peer dependency: eslint@9.27.0
> npm warn node_modules/eslint
> npm warn   peer eslint@"^8.57.0 || ^9.0.0" from @typescript-eslint/parser@8.20.0
> npm warn   node_modules/eslint-config-next/node_modules/@typescript-eslint/parser
> npm warn     @typescript-eslint/parser@"^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0" from eslint-config-next@15.1.5
> npm warn     node_modules/eslint-config-next
> npm warn     1 more (@typescript-eslint/eslint-plugin)
> npm warn ERESOLVE overriding peer dependency
> npm warn While resolving: @typescript-eslint/type-utils@8.20.0
> npm warn Found: eslint@8.56.0
> npm warn node_modules/eslint
> npm warn   dev eslint@"^8" from the root project
> npm warn   7 more (@eslint-community/eslint-utils, eslint-config-next, ...)
> npm warn
> npm warn Could not resolve dependency:
> npm warn peer eslint@"^8.57.0 || ^9.0.0" from @typescript-eslint/type-utils@8.20.0
> npm warn node_modules/eslint-config-next/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils
> npm warn   @typescript-eslint/type-utils@"8.20.0" from @typescript-eslint/eslint-plugin@8.20.0
> npm warn   node_modules/eslint-config-next/node_modules/@typescript-eslint/eslint-plugin
> npm warn
> npm warn Conflicting peer dependency: eslint@9.27.0
> npm warn node_modules/eslint
> npm warn   peer eslint@"^8.57.0 || ^9.0.0" from @typescript-eslint/type-utils@8.20.0
> npm warn   node_modules/eslint-config-next/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils
> npm warn     @typescript-eslint/type-utils@"8.20.0" from @typescript-eslint/eslint-plugin@8.20.0
> npm warn     node_modules/eslint-config-next/node_modules/@typescript-eslint/eslint-plugin
> npm warn ERESOLVE overriding peer dependency
> npm warn While resolving: @typescript-eslint/utils@8.20.0
> npm warn Found: eslint@8.56.0
> npm warn node_modules/eslint
> npm warn   dev eslint@"^8" from the root project
> npm warn   7 more (@eslint-community/eslint-utils, eslint-config-next, ...)
> npm warn
> npm warn Could not resolve dependency:
> npm warn peer eslint@"^8.57.0 || ^9.0.0" from @typescript-eslint/utils@8.20.0
> npm warn node_modules/eslint-config-next/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils
> npm warn   @typescript-eslint/utils@"8.20.0" from @typescript-eslint/eslint-plugin@8.20.0
> npm warn   node_modules/eslint-config-next/node_modules/@typescript-eslint/eslint-plugin
> npm warn   1 more (@typescript-eslint/type-utils)
> npm warn
> npm warn Conflicting peer dependency: eslint@9.27.0
> npm warn node_modules/eslint
> npm warn   peer eslint@"^8.57.0 || ^9.0.0" from @typescript-eslint/utils@8.20.0
> npm warn   node_modules/eslint-config-next/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils
> npm warn     @typescript-eslint/utils@"8.20.0" from @typescript-eslint/eslint-plugin@8.20.0
> npm warn     node_modules/eslint-config-next/node_modules/@typescript-eslint/eslint-plugin
> npm warn     1 more (@typescript-eslint/type-utils)
> npm error Exit handler never called!
> npm error This is an error with npm itself. Please report this error at:
> npm error   <https://github.com/npm/cli/issues>
> npm error A complete log of this run can be found in: /.npm/_logs/2025-05-20T06_10_46_853Z-debug-0.log
> 
> 
> 
> </details>

<!-- end of auto-generated comment: all tool run failures by coderabbit.ai -->

<!-- announcements_start -->

> [!NOTE]
> <details>
> <summary>⚡️ AI Code Reviews for VS Code, Cursor, Windsurf</summary>
> 
> CodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback.
> Learn more [here](http://coderabbit.ai/ide).
> 
> </details>

---

> [!NOTE]
> <details>
> <summary>⚡️ Faster reviews with caching</summary>
> 
> CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure `Review - Disable Cache` at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the `Data Retention` setting under your Organization Settings.
> Enjoy the performance boost—your workflow just got faster.
> 
> </details>

<!-- announcements_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=dennis-adrian/glitter-nextjs&utm_content=199):

- 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](https://www.coderabbit.ai/contact-us/support) 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](https://docs.coderabbit.ai/finishing-touches/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](https://docs.coderabbit.ai/guides/configure-coderabbit) 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](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE