Compare commits

...

2 Commits

Author SHA1 Message Date
Rodolfo Ruiz
01a19b9144 chore: improve the ui for Products 2025-09-06 19:53:10 -06:00
Rodolfo Ruiz
74d6a8b269 chore: fix the edit popup 2025-09-06 19:48:21 -06:00
3 changed files with 158 additions and 174 deletions

View File

@@ -254,7 +254,7 @@ export default function Categories() {
}} }}
> >
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 2, flexWrap: 'wrap' }}> <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 2, flexWrap: 'wrap' }}>
<Typography variant="h6">Categories</Typography> <Typography color='text.primary' variant="h6">Categories</Typography>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}> <Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
<ToggleButtonGroup <ToggleButtonGroup

View File

@@ -1,6 +1,6 @@
// src/private/furniture/AddOrEditFurnitureVariantForm.jsx // src/private/furniture/AddOrEditFurnitureVariantForm.jsx
import { useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useState } from 'react';
import { Box, Button, TextField, MenuItem, Grid, CircularProgress } from '@mui/material'; import { Box, Button, TextField, MenuItem, CircularProgress } from '@mui/material';
import FurnitureVariantApi from '../../../api/ProductsApi'; import FurnitureVariantApi from '../../../api/ProductsApi';
import CategoriesApi from '../../../api/CategoriesApi'; import CategoriesApi from '../../../api/CategoriesApi';
import TagTypeApi from '../../../api/TagTypeApi'; import TagTypeApi from '../../../api/TagTypeApi';
@@ -197,154 +197,149 @@ export default function AddOrEditProductCollectionForm({ initialData, onAdd, onC
return ( return (
<Box> <Box>
<Grid container spacing={2}> <Box display="flex" flexDirection="column" gap={2}>
<Grid item xs={12} md={6}> {/* Name */}
<TextField label="Model Id" fullWidth value={form.modelId} onChange={(e) => setVal('modelId', e.target.value)} /> <TextField
</Grid> label="Name"
<Grid item xs={12} md={6}> fullWidth
<TextField label="Name" fullWidth value={form.name} onChange={(e) => setVal('name', e.target.value)} /> value={form.name}
</Grid> onChange={(e) => setVal('name', e.target.value)}
sx={{ mt: 1 }}
/>
{/* Clasificación */} {/* Category / Provider */}
<Grid item xs={12} md={6}> <TextField
<TextField select
select label="Category"
label="Category" fullWidth
fullWidth value={form.categoryId}
value={form.categoryId} onChange={(e) => setVal('categoryId', e.target.value)}
onChange={(e) => setVal('categoryId', e.target.value)} helperText="Se envía el tagName por ahora"
helperText="Se envía el tagName por ahora" >
> {loadingTags && <MenuItem value="" disabled><CircularProgress size={16} /> Cargando</MenuItem>}
{loadingTags && <MenuItem value="" disabled><CircularProgress size={16} /> Cargando</MenuItem>} {!loadingTags && options.categories.filter(t => t.status !== 'Inactive').map(tag => (
{!loadingTags && options.categories.filter(t => t.status !== 'Inactive').map(tag => ( <MenuItem key={tag._id?.$oid || tag._id || tag.id} value={tag.tagName}>{tag.tagName}</MenuItem>
<MenuItem key={tag._id?.$oid || tag._id || tag.id} value={tag.tagName}>{tag.tagName}</MenuItem> ))}
))} </TextField>
</TextField> <TextField
</Grid> select
label="Provider"
fullWidth
value={form.providerId}
onChange={(e) => setVal('providerId', e.target.value)}
>
{loadingTags && <MenuItem value="" disabled><CircularProgress size={16} /> Cargando</MenuItem>}
{!loadingTags && options.providers.filter(t => t.status !== 'Inactive').map(tag => (
<MenuItem key={tag._id?.$oid || tag._id || tag.id} value={tag.tagName}>{tag.tagName}</MenuItem>
))}
</TextField>
<Grid item xs={12} md={6}> <Box display="flex" gap={2}>
<TextField {/* Color */}
select <Box flex={1}>
label="Provider" <TextField
fullWidth select
value={form.providerId} label="Color"
onChange={(e) => setVal('providerId', e.target.value)} fullWidth
> value={form.color}
{loadingTags && <MenuItem value="" disabled><CircularProgress size={16} /> Cargando</MenuItem>} onChange={(e) => setVal('color', e.target.value)}
{!loadingTags && options.providers.filter(t => t.status !== 'Inactive').map(tag => ( >
<MenuItem key={tag._id?.$oid || tag._id || tag.id} value={tag.tagName}>{tag.tagName}</MenuItem> {loadingTags && <MenuItem value="" disabled><CircularProgress size={16} /> Cargando</MenuItem>}
))} {!loadingTags && options.colors.filter(t => t.status !== 'Inactive').map(tag => (
</TextField> <MenuItem key={tag._id?.$oid || tag._id || tag.id} value={tag.tagName}>{tag.tagName}</MenuItem>
</Grid> ))}
</TextField>
</Box>
{/* Line */}
<Box flex={1}>
<TextField
select
label="Line"
fullWidth
value={form.line}
onChange={(e) => setVal('line', e.target.value)}
>
{loadingTags && <MenuItem value="" disabled><CircularProgress size={16} /> Cargando</MenuItem>}
{!loadingTags && options.lines.filter(t => t.status !== 'Inactive').map(tag => (
<MenuItem key={tag._id?.$oid || tag._id || tag.id} value={tag.tagName}>{tag.tagName}</MenuItem>
))}
</TextField>
</Box>
{/* Material */}
<Box flex={1}>
<TextField
select
label="Material"
fullWidth
value={form.attributes.material}
onChange={(e) => setVal('attributes.material', e.target.value)}
>
{loadingTags && <MenuItem value="" disabled><CircularProgress size={16} /> Cargando</MenuItem>}
{!loadingTags && options.materials.filter(t => t.status !== 'Inactive').map(tag => (
<MenuItem key={tag._id?.$oid || tag._id || tag.id} value={tag.tagName}>{tag.tagName}</MenuItem>
))}
</TextField>
</Box>
</Box>
{/* Específicos de variante */} <Box display="flex" gap={2}>
<Grid item xs={12} md={4}> {/* Price */}
<TextField <Box flex={1}>
select <TextField label="Price" type="number" fullWidth value={form.price} onChange={(e) => setVal('price', e.target.value)} />
label="Color" </Box>
fullWidth {/* Stock */}
value={form.color} <Box flex={1}>
onChange={(e) => setVal('color', e.target.value)} <TextField label="Stock" type="number" fullWidth value={form.stock} onChange={(e) => setVal('stock', e.target.value)} />
> </Box>
{loadingTags && <MenuItem value="" disabled><CircularProgress size={16} /> Cargando</MenuItem>} {/* Currency */}
{!loadingTags && options.colors.filter(t => t.status !== 'Inactive').map(tag => ( <Box flex={1}>
<MenuItem key={tag._id?.$oid || tag._id || tag.id} value={tag.tagName}>{tag.tagName}</MenuItem> <TextField
))} select
</TextField> label="Currency"
</Grid> fullWidth
value={form.currency}
onChange={(e) => setVal('currency', e.target.value)}
>
{loadingTags && <MenuItem value="" disabled><CircularProgress size={16} /> Cargando</MenuItem>}
{!loadingTags && options.currencies.filter(t => t.status !== 'Inactive').map(tag => (
<MenuItem key={tag._id?.$oid || tag._id || tag.id} value={tag.tagName}>{tag.tagName}</MenuItem>
))}
</TextField>
</Box>
</Box>
<Grid item xs={12} md={4}> {/* Attributes */}
<TextField <TextField
select select
label="Line" label="Legs"
fullWidth fullWidth
value={form.line} value={form.attributes.legs}
onChange={(e) => setVal('line', e.target.value)} onChange={(e) => setVal('attributes.legs', e.target.value)}
> >
{loadingTags && <MenuItem value="" disabled><CircularProgress size={16} /> Cargando</MenuItem>} {loadingTags && <MenuItem value="" disabled><CircularProgress size={16} /> Cargando</MenuItem>}
{!loadingTags && options.lines.filter(t => t.status !== 'Inactive').map(tag => ( {!loadingTags && options.legs.filter(t => t.status !== 'Inactive').map(tag => (
<MenuItem key={tag._id?.$oid || tag._id || tag.id} value={tag.tagName}>{tag.tagName}</MenuItem> <MenuItem key={tag._id?.$oid || tag._id || tag.id} value={tag.tagName}>{tag.tagName}</MenuItem>
))} ))}
</TextField> </TextField>
</Grid> <TextField
select
<Grid item xs={12} md={4}> label="Origin"
<TextField fullWidth
select value={form.attributes.origin}
label="Currency" onChange={(e) => setVal('attributes.origin', e.target.value)}
fullWidth >
value={form.currency} {loadingTags && <MenuItem value="" disabled><CircularProgress size={16} /> Cargando</MenuItem>}
onChange={(e) => setVal('currency', e.target.value)} {!loadingTags && options.origins.filter(t => t.status !== 'Inactive').map(tag => (
> <MenuItem key={tag._id?.$oid || tag._id || tag.id} value={tag.tagName}>{tag.tagName}</MenuItem>
{loadingTags && <MenuItem value="" disabled><CircularProgress size={16} /> Cargando</MenuItem>} ))}
{!loadingTags && options.currencies.filter(t => t.status !== 'Inactive').map(tag => ( </TextField>
<MenuItem key={tag._id?.$oid || tag._id || tag.id} value={tag.tagName}>{tag.tagName}</MenuItem>
))}
</TextField>
</Grid>
{/* Atributos como catálogos */}
<Grid item xs={12} md={4}>
<TextField
select
label="Material"
fullWidth
value={form.attributes.material}
onChange={(e) => setVal('attributes.material', e.target.value)}
>
{loadingTags && <MenuItem value="" disabled><CircularProgress size={16} /> Cargando</MenuItem>}
{!loadingTags && options.materials.filter(t => t.status !== 'Inactive').map(tag => (
<MenuItem key={tag._id?.$oid || tag._id || tag.id} value={tag.tagName}>{tag.tagName}</MenuItem>
))}
</TextField>
</Grid>
<Grid item xs={12} md={4}>
<TextField
select
label="Legs"
fullWidth
value={form.attributes.legs}
onChange={(e) => setVal('attributes.legs', e.target.value)}
>
{loadingTags && <MenuItem value="" disabled><CircularProgress size={16} /> Cargando</MenuItem>}
{!loadingTags && options.legs.filter(t => t.status !== 'Inactive').map(tag => (
<MenuItem key={tag._id?.$oid || tag._id || tag.id} value={tag.tagName}>{tag.tagName}</MenuItem>
))}
</TextField>
</Grid>
<Grid item xs={12} md={4}>
<TextField
select
label="Origin"
fullWidth
value={form.attributes.origin}
onChange={(e) => setVal('attributes.origin', e.target.value)}
>
{loadingTags && <MenuItem value="" disabled><CircularProgress size={16} /> Cargando</MenuItem>}
{!loadingTags && options.origins.filter(t => t.status !== 'Inactive').map(tag => (
<MenuItem key={tag._id?.$oid || tag._id || tag.id} value={tag.tagName}>{tag.tagName}</MenuItem>
))}
</TextField>
</Grid>
{/* Números */}
<Grid item xs={12} md={4}>
<TextField label="Stock" type="number" fullWidth value={form.stock} onChange={(e) => setVal('stock', e.target.value)} />
</Grid>
<Grid item xs={12} md={4}>
<TextField label="Price" type="number" fullWidth value={form.price} onChange={(e) => setVal('price', e.target.value)} />
</Grid>
{/* Status */} {/* Status */}
<Grid item xs={12} md={4}> <TextField select label="Status" fullWidth value={form.status} onChange={(e) => setVal('status', e.target.value)}>
<TextField select label="Status" fullWidth value={form.status} onChange={(e) => setVal('status', e.target.value)}> <MenuItem value="Active">Active</MenuItem>
<MenuItem value="Active">Active</MenuItem> <MenuItem value="Inactive">Inactive</MenuItem>
<MenuItem value="Inactive">Inactive</MenuItem> </TextField>
</TextField> </Box>
</Grid>
</Grid>
<Box display="flex" justifyContent="flex-end" mt={3} gap={1}> <Box display="flex" justifyContent="flex-end" mt={3} gap={1}>
<Button onClick={onCancel} className="button-transparent">Cancel</Button> <Button onClick={onCancel} className="button-transparent">Cancel</Button>

View File

@@ -80,16 +80,7 @@ export default function ProductCollections() {
return found?.tagName || String(value); return found?.tagName || String(value);
}; };
}; };
const labelCategory = useMemo(() => buildLabelResolver(TYPE_NAMES.category), [byType]);
const labelProvider = useMemo(() => buildLabelResolver(TYPE_NAMES.provider), [byType]);
const labelColor = useMemo(() => buildLabelResolver(TYPE_NAMES.color), [byType]);
const labelLine = useMemo(() => buildLabelResolver(TYPE_NAMES.line), [byType]);
const labelCurrency = useMemo(() => buildLabelResolver(TYPE_NAMES.currency), [byType]);
const labelMaterial = useMemo(() => buildLabelResolver(TYPE_NAMES.material), [byType]);
const labelLegs = useMemo(() => buildLabelResolver(TYPE_NAMES.legs), [byType]);
const labelOrigin = useMemo(() => buildLabelResolver(TYPE_NAMES.origin), [byType]);
// Cargar TagTypes + Tags // Cargar TagTypes + Tags
useEffect(() => { useEffect(() => {
let mounted = true; let mounted = true;
@@ -273,10 +264,16 @@ export default function ProductCollections() {
]; ];
return ( return (
<Box sx={{ height: 'calc(100vh - 64px - 64px)', display: 'flex', flexDirection: 'column', gap: 2 }}> <Box
<SectionContainer sx={{ px: 0, maxWidth: '100%!important', width: '100%' }}> sx={{
height: 'calc(100vh - 64px - 64px)',
display: 'flex',
flexDirection: 'column',
gap: 2,
}}
>
<Box display="flex" alignItems="center" justifyContent="space-between" mb={2} flexWrap="wrap" gap={2}> <Box display="flex" alignItems="center" justifyContent="space-between" mb={2} flexWrap="wrap" gap={2}>
<Typography variant="h6">Product Collection</Typography> <Typography color='text.primary' variant="h6">Product Collection</Typography>
<Box display="flex" alignItems="center" gap={2}> <Box display="flex" alignItems="center" gap={2}>
<ToggleButtonGroup <ToggleButtonGroup
value={statusFilter} value={statusFilter}
@@ -308,27 +305,20 @@ export default function ProductCollections() {
getRowHeight={() => 'auto'} getRowHeight={() => 'auto'}
columnBuffer={0} columnBuffer={0}
sx={{ sx={{
width: '100%', height: '100%',
'& .MuiDataGrid-cell': { '& .MuiDataGrid-cell, & .MuiDataGrid-columnHeader': {
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
whiteSpace: 'normal',
wordBreak: 'break-word',
minHeight: '100%',
}, },
'& .MuiDataGrid-columnHeader': { '& .MuiDataGrid-filler': {
display: 'flex', display: 'none',
alignItems: 'center',
whiteSpace: 'normal',
wordBreak: 'break-word',
},
'& .MuiDataGrid-virtualScroller': {
overflowX: 'auto',
},
'& .MuiDataGrid-main': {
minWidth: '1000px',
}, },
}} }}
slots={{
noRowsOverlay: () => (
<Box sx={{ p: 2 }}>No product collection found. Try switching the status filter to "All".</Box>
),
}}
/> />
</Box> </Box>
@@ -349,7 +339,6 @@ export default function ProductCollections() {
/> />
</DialogContent> </DialogContent>
</Dialog> </Dialog>
</SectionContainer>
</Box> </Box>
); );
} }