Vista (intefaz y bd), esquema y endpoints de store agregados
This commit is contained in:
@@ -4,7 +4,8 @@ import {
|
||||
ApiResponseSchema,
|
||||
InventoryTable,
|
||||
productMutate,
|
||||
editInventory
|
||||
// editInventory,
|
||||
productApiResponseSchema
|
||||
} from '../schemas/inventory';
|
||||
|
||||
import { auth } from '@/lib/auth';
|
||||
@@ -27,8 +28,8 @@ export const getInventoryAction = async (params: {
|
||||
|
||||
const [error, response] = await safeFetchApi(
|
||||
ApiResponseSchema,
|
||||
`/inventory?${searchParams}`,
|
||||
'GET',
|
||||
`/products/inventory?${searchParams}`,
|
||||
'GET'
|
||||
);
|
||||
|
||||
if (error) {
|
||||
@@ -53,6 +54,52 @@ export const getInventoryAction = async (params: {
|
||||
};
|
||||
}
|
||||
|
||||
export const getAllProducts = async (params: {
|
||||
page?: number;
|
||||
limit?: number;
|
||||
search?: string;
|
||||
sortBy?: string;
|
||||
sortOrder?: 'asc' | 'desc';
|
||||
}) => {
|
||||
|
||||
const session = await auth()
|
||||
|
||||
const searchParams = new URLSearchParams({
|
||||
page: (params.page || 1).toString(),
|
||||
limit: (params.limit || 10).toString(),
|
||||
...(params.search && { search: params.search }),
|
||||
...(params.sortBy && { sortBy: params.sortBy }),
|
||||
...(params.sortOrder && { sortOrder: params.sortOrder }),
|
||||
})
|
||||
|
||||
const id = session?.user.id
|
||||
|
||||
const [error, response] = await safeFetchApi(
|
||||
productApiResponseSchema,
|
||||
`/products/store?${searchParams}`,
|
||||
'GET'
|
||||
);
|
||||
|
||||
if (error) {
|
||||
console.error('Error:', error);
|
||||
throw new Error(error.message);
|
||||
}
|
||||
|
||||
return {
|
||||
data: response?.data || [],
|
||||
meta: response?.meta || {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
totalCount: 0,
|
||||
totalPages: 1,
|
||||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
nextPage: null,
|
||||
previousPage: null,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const createProductAction = async (payload: InventoryTable) => {
|
||||
const session = await auth()
|
||||
const userId = session?.user?.id
|
||||
@@ -62,14 +109,14 @@ export const createProductAction = async (payload: InventoryTable) => {
|
||||
|
||||
const [error, data] = await safeFetchApi(
|
||||
productMutate,
|
||||
'/inventory',
|
||||
'/products',
|
||||
'POST',
|
||||
payloadWithoutId,
|
||||
);
|
||||
|
||||
if (error) {
|
||||
console.error(error);
|
||||
throw new Error('Error al crear el usuario');
|
||||
throw new Error('Error al crear el producto');
|
||||
}
|
||||
|
||||
return payloadWithoutId;
|
||||
@@ -81,16 +128,14 @@ export const updateUserAction = async (payload: InventoryTable) => {
|
||||
|
||||
const [error, data] = await safeFetchApi(
|
||||
productMutate,
|
||||
`/inventory/${id}`,
|
||||
`/products/${id}`,
|
||||
'PATCH',
|
||||
payloadWithoutId,
|
||||
);
|
||||
|
||||
// console.log(data);
|
||||
if (error) {
|
||||
console.error(error);
|
||||
|
||||
throw new Error(error?.message || 'Error al actualizar el usuario');
|
||||
throw new Error(error?.message || 'Error al actualizar el producto');
|
||||
}
|
||||
return data;
|
||||
} catch (error) {
|
||||
@@ -98,17 +143,14 @@ export const updateUserAction = async (payload: InventoryTable) => {
|
||||
}
|
||||
}
|
||||
|
||||
export const deleteUserAction = async (id: Number) => {
|
||||
export const deleteProductAction = async (id: Number) => {
|
||||
const [error] = await safeFetchApi(
|
||||
productMutate,
|
||||
`/users/${id}`,
|
||||
`/products/${id}`,
|
||||
'DELETE'
|
||||
)
|
||||
|
||||
console.log(error);
|
||||
|
||||
|
||||
// if (error) throw new Error(error.message || 'Error al eliminar el usuario')
|
||||
if (error) throw new Error(error.message || 'Error al eliminar el usuario')
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@repo/shadcn/form';
|
||||
import { Textarea } from '@repo/shadcn/textarea';
|
||||
import { Input } from '@repo/shadcn/input';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useCreateUser } from "@/feactures/inventory/hooks/use-mutation";
|
||||
@@ -83,20 +84,6 @@ export function CreateForm({
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="description"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Descripción</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="price"
|
||||
@@ -113,6 +100,21 @@ export function CreateForm({
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="description"
|
||||
render={({ field }) => (
|
||||
<FormItem className='col-span-2'>
|
||||
<FormLabel>Descripción</FormLabel>
|
||||
<FormControl>
|
||||
{/* <Input {...field} /> */}
|
||||
<Textarea {...field} className="resize-none"/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="stock"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { DataTable } from '@repo/shadcn/table/data-table';
|
||||
import { DataTableSkeleton } from '@repo/shadcn/table/data-table-skeleton';
|
||||
import { columns } from './product-tables/columns';
|
||||
import { useProductQuery } from '../../hooks/use-query-users';
|
||||
import { useProductQuery } from '../../hooks/use-query-products';
|
||||
|
||||
interface SurveysAdminListProps {
|
||||
initialPage: number;
|
||||
|
||||
@@ -13,6 +13,7 @@ import { Input } from '@repo/shadcn/input';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useUpdateUser } from "@/feactures/inventory/hooks/use-mutation";
|
||||
import { editInventory, formDataInput, EditInventory } from '@/feactures/inventory/schemas/inventory'; // Renombrado EditInventory para claridad
|
||||
import { Textarea } from '@repo/shadcn/components/ui/textarea';
|
||||
|
||||
interface UpdateFormProps {
|
||||
onSuccess?: () => void;
|
||||
@@ -87,19 +88,7 @@ export function UpdateForm({
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="description"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Descripción</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
@@ -116,6 +105,21 @@ export function UpdateForm({
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="description"
|
||||
render={({ field }) => (
|
||||
<FormItem className='col-span-2'>
|
||||
<FormLabel>Descripción</FormLabel>
|
||||
<FormControl>
|
||||
{/* <Input {...field} /> */}
|
||||
<Textarea {...field} className="resize-none"/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="stock"
|
||||
|
||||
@@ -17,7 +17,7 @@ export function UsersHeader() {
|
||||
description="Gestione aquí los productos que usted registre en la plataforma"
|
||||
/>
|
||||
<Button onClick={() => setOpen(true)} size="sm">
|
||||
<Plus className="mr-2 h-4 w-4" /> Agregar Producto
|
||||
<Plus className="h-4 w-4" /><span className='hidden md:inline'>Agregar Producto</span>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
// Este componente maneja la lista de encuestas en el panel de administración
|
||||
// Funcionalidades:
|
||||
// - Muestra todas las encuestas en una tabla
|
||||
// - Permite editar encuestas existentes
|
||||
// - Permite eliminar encuestas con confirmación
|
||||
// - Muestra el estado (publicada/borrador), fechas y conteo de respuestas
|
||||
|
||||
|
||||
'use client';
|
||||
|
||||
import { Button } from '@repo/shadcn/button';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from '@repo/shadcn/card';
|
||||
import { useRouter } from 'next/navigation';
|
||||
// import { useSurveysForUserQuery } from '@/feactures/surveys/hooks/use-query-surveys';
|
||||
import { useAllProductQuery } from '@/feactures/inventory/hooks/use-query-products';
|
||||
import { allProducts } from '../../schemas/inventory';
|
||||
import { Badge } from '@repo/shadcn/badge';
|
||||
import { BadgeCheck } from 'lucide-react';
|
||||
|
||||
export function SurveyList() {
|
||||
|
||||
const router = useRouter();
|
||||
const {data: produts} = useAllProductQuery()
|
||||
|
||||
const handleRespond = (surveyId: number) => {
|
||||
router.push(`/dashboard/productos/${surveyId}`);
|
||||
};
|
||||
|
||||
// console.log(produts?.data)
|
||||
return (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{produts?.meta.totalPages === 0 ? (
|
||||
<div className="col-span-full text-center py-10">
|
||||
<p className="text-muted-foreground">No hay productos disponibles en este momento.</p>
|
||||
</div>
|
||||
) : (
|
||||
produts?.data.map((data: allProducts) => (
|
||||
|
||||
<Card key={data.id} className="flex flex-col">
|
||||
<CardHeader>
|
||||
<CardTitle>{data.title}</CardTitle>
|
||||
<CardDescription>{data.description}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="flex-grow">
|
||||
<div className="space-y-2 text-sm">
|
||||
<div className="flex justify-between">
|
||||
<img src="/data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="flex justify-center">
|
||||
<Button
|
||||
className="w-full"
|
||||
onClick={() => handleRespond(Number(data.id))}
|
||||
>
|
||||
Ver
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
'use client'
|
||||
import { useSafeQuery } from "@/hooks/use-safe-query";
|
||||
import { getInventoryAction} from "../actions/actions";
|
||||
import { getInventoryAction, getAllProducts } from "../actions/actions";
|
||||
|
||||
// Hook for users
|
||||
export function useProductQuery(params = {}) {
|
||||
return useSafeQuery(['product',params], () => getInventoryAction(params))
|
||||
}
|
||||
|
||||
export function useAllProductQuery(params = {}) {
|
||||
return useSafeQuery(['product',params], () => getAllProducts(params))
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
import { user } from '@/feactures/auth/schemas/register';
|
||||
import { all } from 'axios';
|
||||
import { z } from 'zod';
|
||||
|
||||
export type InventoryTable = z.infer<typeof product>;
|
||||
export type EditInventory = z.infer<typeof editInventory>; //output
|
||||
export type formDataInput = z.input<typeof editInventory>;
|
||||
export type ProductApiResponseSchema = z.infer<typeof productApiResponseSchema>;
|
||||
export type allProducts = z.infer<typeof allProducts>;
|
||||
|
||||
export const product = z.object({
|
||||
id: z.number().optional(),
|
||||
@@ -27,6 +31,18 @@ export const editInventory = z.object({
|
||||
userId: z.number().optional(),
|
||||
})
|
||||
|
||||
export const allProducts = z.object({
|
||||
id: z.number().optional(),
|
||||
title: z.string().min(5, { message: "Debe de tener 5 o más caracteres" }),
|
||||
description: z.string().min(10, { message: "Debe de tener 10 o más caracteres" }),
|
||||
stock: z.number(),
|
||||
price: z.string(),
|
||||
urlImg: z.string(),
|
||||
user: z.object({
|
||||
userId: z.number(),
|
||||
username: z.string(),
|
||||
})
|
||||
})
|
||||
|
||||
export const ApiResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
@@ -43,6 +59,21 @@ export const ApiResponseSchema = z.object({
|
||||
}),
|
||||
})
|
||||
|
||||
export const productApiResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
data: z.array(allProducts),
|
||||
meta: z.object({
|
||||
page: z.number(),
|
||||
limit: z.number(),
|
||||
totalCount: z.number(),
|
||||
totalPages: z.number(),
|
||||
hasNextPage: z.boolean(),
|
||||
hasPreviousPage: z.boolean(),
|
||||
nextPage: z.number().nullable(),
|
||||
previousPage: z.number().nullable(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const productMutate = z.object({
|
||||
message: z.string(),
|
||||
data: product,
|
||||
|
||||
Reference in New Issue
Block a user