Initial ItemsInfo (to be improved)

This commit is contained in:
Tim
2025-06-13 19:26:17 +02:00
parent 3adbc9a1d1
commit a21b5a1f7e
5 changed files with 202 additions and 19 deletions

View File

@@ -102,6 +102,11 @@
"surname": "Nachname",
"language": "Sprache",
"password": "Passwort",
"adminize": "Admin ernennen",
"unadminize": "Admin abernennen",
"actualPrice": "Endpreis in €",
"stock": "Bestand",
"price100": "Preis in ct",
"discount100": "Rabatt in %",
"deleteProduct": "Produkt löschen",
"description": "Beschreibung",
"images": "Bilder"
}

View File

@@ -102,6 +102,11 @@
"surname": "Surname",
"language": "Language",
"password": "Password",
"adminize": "Make Admin",
"unadminize": "Revoke Admin"
"actualPrice": "Price in €",
"stock": "Stock",
"price100": "Price in ct",
"discount100": "Discount in %",
"deleteProduct": "Delete Product",
"description": "Description",
"images": "Images"
}

View File

@@ -5,6 +5,7 @@ type Item = {
description: string;
price100: number;
stock: number;
stockExpected: number;
category: string;
rating: number;
discount100: number;

View File

@@ -1,27 +1,199 @@
import { Typography, Box, useTheme } from "@mui/material";
import DeleteIcon from "@mui/icons-material/Delete";
import EditIcon from "@mui/icons-material/Edit";
import {Box, Button, IconButton, Toolbar, useTheme} from "@mui/material";
import Item from "../../components/Item";
import {useTranslation} from "react-i18next";
import {DataGrid, GridColDef, GridRowId, GridRowSelectionModel} from "@mui/x-data-grid";
import {useEffect, useState} from "react";
import {Gauge} from "@mui/x-charts";
export default function ItemInfo() {
export default function ItemsInfo() {
const theme = useTheme();
const {t} = useTranslation();
//TODO: add colors to gauges for rating adn stock
function mapValueToColor(minVal: number, maxVal: number, actualVal: number): string {
const clamped = Math.min(Math.max(actualVal, minVal), maxVal);
// Calculate interpolation ratio (0-1)
const ratio = maxVal !== minVal
? (clamped - minVal) / (maxVal - minVal)
: 0;
const red = Math.floor(255 * (1 - ratio));
const green = Math.floor(255 * ratio)
const redHex = red.toString(16).padStart(2, '0').toUpperCase();
const greenHex = green.toString(16).padStart(2, '0').toUpperCase();
return `#${redHex}${greenHex}00`; // Blue is always 00
}
function handleIconEdit(item: Item) {
//TODO: implement
console.log("IconEdit", item);
}
const _rows: Item[] = [
{
id: "1",
uuid: "uuid123",
name: "Item",
description: "Super duper geil <b>wichtiger text </b>",
price100: 1000,
stock: 100,
stockExpected: 1200,
category: "garden",
rating: 5,
discount100: 21,
},
{
id: "2",
uuid: "uuid12312412",
name: "Schlauch",
description: "Schlauchiger Schlauch für Schlauchige Angelegenheiten",
price100: 10,
stock: 50,
stockExpected: 100,
category: "technicalComponents",
rating: 10,
discount100: 21,
},
]
//TODO: get per REST
const [rows, setRows] = useState<Item[]>(_rows);
const [selectedRows, setSelectedRows] = useState<Set<GridRowId>>(new Set());
const handleSelectionChange = (newSelection: GridRowSelectionModel) => {
setSelectedRows(newSelection.ids);
};
const handleDeleteSelected = async () => {
selectedRows.forEach((row) => {
//TODO: send delete command, or send deleteall
console.log(row);
})
setRows(rows.filter((row) => !selectedRows.has(row.id)));
};
const columns: GridColDef<(typeof rows)[number]>[] = [
{field: 'id', headerName: 'ID', width: 60},
{
field: 'uuid',
headerName: "UUID",
type: "string",
width: 120,
editable: true
},
{
field: 'name',
headerName: t('name'),
width: 150,
editable: true,
},
{
field: 'category',
headerName: t('category'),
width: 150,
editable: true,
},
{
field: 'description',
headerName: t('description'),
width: 150,
editable: true,
},
{
field: 'price100',
headerName: t('price100'),
width: 100,
editable: true,
type: 'number'
},
{
field: 'discount100',
headerName: t('discount100'),
width: 120,
editable: true,
type: 'number'
},
{
field: 'stock',
headerName: t('stock'),
width: 100,
editable: true,
type: 'number',
renderCell: params => <Gauge value={params.row.stock} valueMin={0} valueMax={params.row.stockExpected} startAngle={-90} endAngle={90} />
},
{
field: 'rating',
headerName: t('rating'),
width: 100,
editable: true,
type: 'number',
renderCell: params => <Gauge value={params.row.rating} valueMin={0} valueMax={10} startAngle={-90} endAngle={90}/>
},
{ //edit billing information button
field: "actualPrice",
headerName: t('actualPrice'),
width: 90,
editable: false,
valueGetter: (_, row) => (row.price100 / 100 * ((100-row.discount100)/100)).toFixed(2)
},
{
field: 'images',
headerName: t('images'),
width: 90,
editable: false,
renderCell: params => <IconButton onClick={() => handleIconEdit(params.row)}> <EditIcon/> </IconButton>,
}
];
useEffect(() => {
console.log(mapValueToColor(0,10,2))
console.log(mapValueToColor(0,10,7))
}, []);
return (
<Box
className="page-table"
sx={{
minHeight: 200,
display: "flex",
alignItems: "center",
justifyContent: "center",
backgroundColor: theme.palette.background.paper,
color: theme.palette.text.secondary,
borderRadius: 2,
boxShadow: 2,
mt: 4,
p: 4,
textAlign: "center",
color: theme.palette.text.secondary
}}
>
<Typography variant="h6">
🚧 Under construction...
</Typography>
<DataGrid
rows={rows}
columns={columns}
initialState={{}}
checkboxSelection
disableRowSelectionOnClick
onRowSelectionModelChange={handleSelectionChange}
slots={{ toolbar: () => (
<Toolbar>
<Button
variant="contained"
color="error"
startIcon={<DeleteIcon/>}
onClick={handleDeleteSelected}
disabled={selectedRows.size === 0}
sx={{
marginRight: 1
}}
>
{t('deleteProduct')}
</Button>
</Toolbar>
)}}
showToolbar
processRowUpdate={(updatedRow, originalRow) => {
setRows(rows.map(row => row.id === updatedRow.id ? updatedRow : row));
//TODO: make REST callback
return updatedRow;
}}
/>
</Box>
);
}