Guardar y cambiar img al editar productos

This commit is contained in:
2025-08-12 15:58:32 -04:00
parent 8a54bf7138
commit 854b31f594
20 changed files with 162 additions and 50 deletions

View File

@@ -6,6 +6,7 @@ import {
} from '../schemas/refreshToken';
export const resfreshTokenAction = async (refreshToken: RefreshTokenValue) => {
// return null // Descomentar esto evita que se tenga que borrar cache al navegador
const [error, data] = await safeFetchApi(
RefreshTokenResponseSchema,
'/auth/refreshToken',

View File

@@ -64,7 +64,7 @@ export const getAllProducts = async (params: {
sortOrder?: 'asc' | 'desc';
}) => {
const session = await auth()
// const session = await auth()
const searchParams = new URLSearchParams({
page: (params.page || 1).toString(),
@@ -74,7 +74,7 @@ export const getAllProducts = async (params: {
...(params.sortOrder && { sortOrder: params.sortOrder }),
})
const id = session?.user.id
// const id = session?.user.id
const [error, response] = await safeFetchApi(
productApiResponseSchema,
@@ -152,8 +152,8 @@ export const updateUserAction2 = async (payload: InventoryTable) => {
const [error, data] = await safeFetchApi(
test,
`/pictures/upload`,
'POST',
`/products/upload`,
'PATCH',
payload,
);
@@ -161,7 +161,7 @@ export const updateUserAction2 = async (payload: InventoryTable) => {
console.error(error);
throw new Error(error?.message || 'Error al actualizar el producto');
}
// console.log(data);
console.log(data);
return data;
} catch (error) {

View File

@@ -27,7 +27,7 @@ export default function UsersAdminList({
const {data, isLoading} = useProductQuery(filters)
// console.log(data?.data);
console.log(data?.data);
if (isLoading) {
return <DataTableSkeleton columnCount={6} rowCount={initialLimit} />;

View File

@@ -5,13 +5,16 @@ import { CellAction } from './cell-action';
import { InventoryTable } from '../../../schemas/inventory';
export const columns: ColumnDef<InventoryTable>[] = [
{
accessorKey: 'userId',
header: 'ID',
},
{
accessorKey: 'urlImg',
header: 'img',
cell: ({ row }) => {
const url = row.getValue("urlImg") as string | undefined;
return (
<img src={`http://localhost:3000/${url}`} alt="" width={64} height={64} className="rounded"/>
<img src={`http://localhost:3000/uploads/inventory/${row.original.userId}/${row.original.urlImg}`} alt="" width={64} height={64} className="rounded"/>
)
},
},

View File

@@ -22,7 +22,7 @@ import { useUpdateUser } from "@/feactures/inventory/hooks/use-mutation";
import { editInventory, EditInventory } from '@/feactures/inventory/schemas/inventory'; // Renombrado EditInventory para claridad
import { Textarea } from '@repo/shadcn/components/ui/textarea';
import {STATUS} from '@/constants/status'
import { useState } from 'react';
import { useState, useEffect } from 'react';
import {sizeFormate} from "@/feactures/inventory/utils/sizeFormate"
import { z } from 'zod'; // Asegúrate de importar Zod
@@ -58,6 +58,13 @@ export function UpdateForm({
} = useUpdateUser();
const [sizeFile, setSizeFile] = useState('0 bytes');
const [previewUrls, setPreviewUrls] = useState<string[]>([]);
useEffect(() => {
return () => {
previewUrls.forEach(url => URL.revokeObjectURL(url));
};
}, [previewUrls]);
const defaultformValues: EditInventory = { // Usamos el nuevo tipo aquí
id: defaultValues?.id,
@@ -226,7 +233,7 @@ export function UpdateForm({
render={({ field: { onChange, onBlur, name, ref } }) => (
<FormItem>
<FormLabel>Imagen</FormLabel>
<p>Peso máximo: 5MB / {sizeFile}</p>
<p>Peso máximo: 5MB / {sizeFile} <span className='text-xs text-destructive'>(Máximo 10 archivos)</span></p>
<FormControl>
<Input
type="file"
@@ -238,15 +245,31 @@ export function UpdateForm({
if (e.target.files) {
const files = Array.from(e.target.files);
let size = 0;
files.forEach(element => size += element.size)
const tamañoFormateado = sizeFormate(size)
const newPreviewUrls: string[] = [];
files.forEach(element => {
size += element.size;
newPreviewUrls.push(URL.createObjectURL(element));
});
const tamañoFormateado = sizeFormate(size);
setSizeFile(tamañoFormateado);
onChange(e.target.files); // Esto ahora pasará FileList a react-hook-form
setPreviewUrls(newPreviewUrls);
onChange(e.target.files);
} else {
setPreviewUrls([]);
}
}}
/>
</FormControl>
<FormMessage />
{previewUrls.length > 0 && (
<div className="mt-2 flex flex-wrap gap-2">
{previewUrls.map((url, index) => (
<img key={index} src={url} alt={`Preview ${index}`} className="w-24 h-24 object-cover rounded-md" />
))}
</div>
)}
</FormItem>
)}
/>

View File

@@ -20,6 +20,7 @@ export const product = z.object({
stock: z.number(),
price: z.string(),
urlImg: z.custom<FileList | undefined>().optional(),
gallery: z.array(z.string()).optional(),
// urlImg: z.string(),
status: z.string(),
userId: z.number().optional()

View File

@@ -69,7 +69,7 @@ const authConfig: NextAuthConfig = {
response.type === 'UNKNOWN_ERROR') // Incluye todos los tipos de error posibles
) {
// Si es un error, lánzalo. Este camino termina aquí.
throw new CredentialsSignin(response.message);
throw new CredentialsSignin( "Error en la API:" + response.message);
}
if (!('user' in response)) {
@@ -136,7 +136,7 @@ const authConfig: NextAuthConfig = {
token.refresh_token = res.tokens.refresh_token;
token.refresh_expire_in = res.tokens.refresh_expire_in;
} catch (error) {
console.log(error);
console.log("error: ",error);
return null;
}
}

View File

@@ -54,7 +54,7 @@ export const safeFetchApi = async <T extends z.ZodSchema<any>>(
[{ type: string; message: string; details?: any } | null, z.infer<T> | null]
> => {
try {
// console.log(url,method,data);
console.log(url,method,data);
const response = await fetchApi({
method,

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 786 KiB