Initial ItemsInfo (to be improved)
This commit is contained in:
Binary file not shown.
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
@@ -5,6 +5,7 @@ type Item = {
|
||||
description: string;
|
||||
price100: number;
|
||||
stock: number;
|
||||
stockExpected: number;
|
||||
category: string;
|
||||
rating: number;
|
||||
discount100: number;
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user