Reformat code

This commit is contained in:
Tim
2025-06-22 13:06:57 +02:00
parent bbd9386530
commit ee50012e20
41 changed files with 1114 additions and 985 deletions

View File

@@ -4,7 +4,7 @@ export enum OrderStatusEnum {
ISSUES = 'ISSUES',
DELIVERED = 'DELIVERED',
CANCELLED = 'CANCELLED',
};
}
type OrderType = {
id: number;

View File

@@ -35,7 +35,13 @@ export default function AccountsInfo() {
const {data, refetch} = useQuery({
queryKey: ["fetchAccounts", loginData],
queryFn: () => fetchAccounts(loginData ? loginData : { email: "", password: "", session: "", customerId: -1, isAdmin: false }),
queryFn: () => fetchAccounts(loginData ? loginData : {
email: "",
password: "",
session: "",
customerId: -1,
isAdmin: false
}),
retry: 3,
retryDelay: 1000,
});
@@ -57,7 +63,11 @@ export default function AccountsInfo() {
const handleDeleteSelected = async () => {
selectedRows.forEach(async (row) => {
await deleteAccount.mutateAsync({ email: loginData?.email || '', session: loginData?.session || '', accountId: row.id as number });
await deleteAccount.mutateAsync({
email: loginData?.email || '',
session: loginData?.session || '',
accountId: row.id as number
});
})
setRows(rows.filter((row) => !selectedRows.has(row.id)));
@@ -65,7 +75,13 @@ export default function AccountsInfo() {
const updateAdmin = useMutation({
mutationFn: (account: AccountType) =>
updateAccountAdmin(account, loginData ? loginData : { email: "", password: "", session: "", customerId: -1, isAdmin: false }),
updateAccountAdmin(account, loginData ? loginData : {
email: "",
password: "",
session: "",
customerId: -1,
isAdmin: false
}),
});

View File

@@ -13,7 +13,13 @@ type CustomerDialogProps = {
setCustomerData: React.Dispatch<React.SetStateAction<CustomerType>>;
};
const CustomerEditDialog: React.FC<CustomerDialogProps> = ({ open, onClose, customerData, setCustomerData, onSubmit }) => {
const CustomerEditDialog: React.FC<CustomerDialogProps> = ({
open,
onClose,
customerData,
setCustomerData,
onSubmit
}) => {
const {t} = useTranslation();

View File

@@ -1,16 +1,15 @@
import React, {useState} from 'react';
import {
Dialog,
DialogTitle,
DialogContent,
DialogActions,
Button,
Box,
Typography,
Alert,
Box,
Button,
CircularProgress,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
IconButton,
Typography,
} from '@mui/material';
import CloudUploadIcon from '@mui/icons-material/CloudUpload';
import CloseIcon from '@mui/icons-material/Close';

View File

@@ -41,7 +41,6 @@ export default function ItemsInfo() {
}
function handleAddItem() {
setNewItemDialog(true);
}
@@ -129,9 +128,12 @@ export default function ItemsInfo() {
width: 100,
editable: true,
type: 'number',
renderCell: params => <Gauge value={Math.min(params.row.stock, params.row.stockExpected)} valueMin={0} valueMax={params.row.stockExpected} startAngle={-90} endAngle={90} sx={{
renderCell: params => <Gauge value={Math.min(params.row.stock, params.row.stockExpected)} valueMin={0}
valueMax={params.row.stockExpected} startAngle={-90} endAngle={90} sx={{
[`& .${gaugeClasses.valueArc}`]: {
fill: () => { return mapValueToColor(0, params.row.stockExpected, params.row.stock) },
fill: () => {
return mapValueToColor(0, params.row.stockExpected, params.row.stock)
},
},
}} text={() => `${params.row.stock}`}/>
},
@@ -141,9 +143,12 @@ export default function ItemsInfo() {
width: 100,
editable: false, //the rating is averaged from ratings
type: 'number',
renderCell: params => <Gauge value={Math.min(params.row.rating, 10)} valueMin={0} valueMax={10} startAngle={-90} endAngle={90} sx={{
renderCell: params => <Gauge value={Math.min(params.row.rating, 10)} valueMin={0} valueMax={10}
startAngle={-90} endAngle={90} sx={{
[`& .${gaugeClasses.valueArc}`]: {
fill: () => { return mapValueToColor(0, 10, params.row.rating) },
fill: () => {
return mapValueToColor(0, 10, params.row.rating)
},
},
}} text={() => `${params.row.rating.toFixed(2)}`}/>
},
@@ -166,7 +171,8 @@ export default function ItemsInfo() {
headerName: t('fsImage'),
width: 90,
editable: false,
renderCell: params => <IconButton onClick={() => handleFarmImageEdit(params.row)}> <EditIcon /> </IconButton>,
renderCell: params => <IconButton onClick={() => handleFarmImageEdit(params.row)}> <EditIcon/>
</IconButton>,
}
];

View File

@@ -1,4 +1,3 @@
import CloseIcon from '@mui/icons-material/Close';
import {
Alert,

View File

@@ -1,12 +1,14 @@
import {
Button,
Card, CardContent,
Card,
CardContent,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
Divider,
List, ListItemText,
List,
ListItemText,
Snackbar,
Stack,
Typography,
@@ -62,7 +64,10 @@ const OrderCard: React.FC<{ order: OrderType; onClick: () => void }> = ({ order,
);
};
const Column: React.FC<PropsWithChildren<{ status: OrderStatusEnum; onDrop: (id: number, status: OrderStatusEnum) => void }>> = ({ status, onDrop, children }) => {
const Column: React.FC<PropsWithChildren<{
status: OrderStatusEnum;
onDrop: (id: number, status: OrderStatusEnum) => void
}>> = ({status, onDrop, children}) => {
const {t} = useTranslation();
const theme = useTheme();
@@ -76,9 +81,29 @@ const Column: React.FC<PropsWithChildren<{ status: OrderStatusEnum; onDrop: (id:
}));
return (
<div ref={drop} style={{ flex: 1, backgroundColor: isOver ? theme.palette.background.paper : 'transparent', padding: 1, minWidth: 300, maxWidth: 400 }}>
<Card sx={{ minHeight: '100%', marginTop: 2, marginLeft: 1, height: '80vh', display: 'flex', flexDirection: 'column' }} elevation={4}>
<CardContent sx={{ flex: 1, display: 'flex', flexDirection: 'column', overflowY: 'auto', height: '100%', padding: 2 }}>
<div ref={drop} style={{
flex: 1,
backgroundColor: isOver ? theme.palette.background.paper : 'transparent',
padding: 1,
minWidth: 300,
maxWidth: 400
}}>
<Card sx={{
minHeight: '100%',
marginTop: 2,
marginLeft: 1,
height: '80vh',
display: 'flex',
flexDirection: 'column'
}} elevation={4}>
<CardContent sx={{
flex: 1,
display: 'flex',
flexDirection: 'column',
overflowY: 'auto',
height: '100%',
padding: 2
}}>
<Typography variant="h6">{t(status)}</Typography>
<div style={{flex: 1, overflowY: 'auto'}}>
{children}
@@ -89,7 +114,11 @@ const Column: React.FC<PropsWithChildren<{ status: OrderStatusEnum; onDrop: (id:
);
};
const EditOrder: React.FC<{ open: boolean; order: OrderType | null; onClose: () => void }> = ({ open, order, onClose }) => {
const EditOrder: React.FC<{ open: boolean; order: OrderType | null; onClose: () => void }> = ({
open,
order,
onClose
}) => {
const {t} = useTranslation();
if (order === null)
@@ -102,7 +131,8 @@ const EditOrder: React.FC<{ open: boolean; order: OrderType | null; onClose: ()
<DialogContent dividers>
{order && (
<Stack spacing={2}>
<Typography variant="subtitle1">{`${t('orderDate')}: ${new Date(order.time).toDateString()}`}</Typography>
<Typography
variant="subtitle1">{`${t('orderDate')}: ${new Date(order.time).toDateString()}`}</Typography>
<Divider/>
<Typography variant="subtitle2">{t('orderedItems')}:</Typography>
<List dense>
@@ -133,7 +163,13 @@ export default function OrdersInfo() {
const {data, refetch, isLoading} = useQuery({
queryKey: ["fetchOrdersAdmin", loginData],
queryFn: () => fetchOrdersAdmin(loginData ? loginData : { email: "", password: "", session: "", customerId: -1, isAdmin: false }),
queryFn: () => fetchOrdersAdmin(loginData ? loginData : {
email: "",
password: "",
session: "",
customerId: -1,
isAdmin: false
}),
retry: 3,
retryDelay: 1000,
});

View File

@@ -5,7 +5,7 @@ import { BarSeriesType } from '@mui/x-charts'
import {useEffect, useState} from "react";
import {useTranslation} from "react-i18next";
import {useQuery} from "@tanstack/react-query";
import { fetchStatisticsVolume, fetchStatisticsRevenue, fetchOrderStatus, fetchStockPercent } from "../query/Queries.tsx";
import {fetchOrderStatus, fetchStatisticsRevenue, fetchStatisticsVolume, fetchStockPercent} from "../query/Queries.tsx";
import {useAccount} from "../AccountProvider.tsx";
import {getColorFromPercent} from "../../util/ColorUtil.tsx";
@@ -31,28 +31,52 @@ export default function StatisticsInfo() {
const {data: dataVolume} = useQuery({
queryKey: ["fetchStatisticsVolume", loginData],
queryFn: () => fetchStatisticsVolume(loginData ? loginData : { email: "", password: "", session: "", customerId: -1, isAdmin: false }),
queryFn: () => fetchStatisticsVolume(loginData ? loginData : {
email: "",
password: "",
session: "",
customerId: -1,
isAdmin: false
}),
retry: 0,
retryDelay: 0,
});
const {data: dataRevenue} = useQuery({
queryKey: ["fetchStatisticsRevenue", loginData],
queryFn: () => fetchStatisticsRevenue(loginData ? loginData : { email: "", password: "", session: "", customerId: -1, isAdmin: false }),
queryFn: () => fetchStatisticsRevenue(loginData ? loginData : {
email: "",
password: "",
session: "",
customerId: -1,
isAdmin: false
}),
retry: 0,
retryDelay: 0,
});
const {data: dataOrderStatus} = useQuery({
queryKey: ["fetchOrderStatus", loginData],
queryFn: () => fetchOrderStatus(loginData ? loginData : { email: "", password: "", session: "", customerId: -1, isAdmin: false }),
queryFn: () => fetchOrderStatus(loginData ? loginData : {
email: "",
password: "",
session: "",
customerId: -1,
isAdmin: false
}),
retry: 0,
retryDelay: 0,
});
const {data: dataStockPercent} = useQuery({
queryKey: ["fetchStockPercent", loginData],
queryFn: () => fetchStockPercent(loginData ? loginData : { email: "", password: "", session: "", customerId: -1, isAdmin: false }),
queryFn: () => fetchStockPercent(loginData ? loginData : {
email: "",
password: "",
session: "",
customerId: -1,
isAdmin: false
}),
retry: 0,
retryDelay: 0,
});
@@ -138,18 +162,27 @@ export default function StatisticsInfo() {
function generateName(percent: string): string {
return ">" + percent + "%";
}
if (dataStockPercent) {
const stockPercent = []
let i = 0
for (let x = 0; x < 10; x++) {
stockPercent.push({value: 0, label: generateName(String(x*10)), color: getColorFromPercent(String(x*10))});
stockPercent.push({
value: 0,
label: generateName(String(x * 10)),
color: getColorFromPercent(String(x * 10))
});
}
for (const cat in dataStockPercent) {
for (const percent in dataStockPercent[cat]) {
let index = stockPercent.findIndex((entry) => entry.label == generateName(percent))
const datapoint = dataStockPercent[cat][percent]
if (index === -1) {
index = stockPercent.push({value: 0, label: generateName(percent), color: getColorFromPercent(percent)}) -1
index = stockPercent.push({
value: 0,
label: generateName(percent),
color: getColorFromPercent(percent)
}) - 1
}
stockPercent[index].value += datapoint
}

View File

@@ -1,12 +1,4 @@
import {
FormControl,
FormControlLabel,
FormLabel,
Radio,
RadioGroup,
Rating,
useTheme,
} from "@mui/material";
import {FormControl, FormControlLabel, FormLabel, Radio, RadioGroup, Rating, useTheme,} from "@mui/material";
import React from "react";
type FilterItemOption = {

View File

@@ -1,5 +1,5 @@
import { Slider, Typography, Box, useTheme } from "@mui/material";
import { useState, useEffect, SyntheticEvent } from "react";
import {Box, Slider, Typography, useTheme} from "@mui/material";
import {SyntheticEvent, useEffect, useState} from "react";
import {useTranslation} from "react-i18next";
type PriceSliderProps = {

View File

@@ -20,7 +20,14 @@ const LoginDialog: React.FC<LoginDialogProps> = ({ open, onClose, loginData, set
const {t} = useTranslation();
const {login} = useAccount();
const [showRegister, setShowRegister] = useState(false);
const [registerData, setRegisterData] = useState<AccountType>({ email: "", password: "", id: 0, customer: { id: 0, name: "", surname: "", address: "", country: "", zip: "" }, langI18n: i18next.language, admin: false });
const [registerData, setRegisterData] = useState<AccountType>({
email: "",
password: "",
id: 0,
customer: {id: 0, name: "", surname: "", address: "", country: "", zip: ""},
langI18n: i18next.language,
admin: false
});
const [showErrorRegister, setShowErrorRegister] = useState(false); // Neuer Zustand für die Anzeige der Fehlermeldung
const [showErrorLogin, setShowErrorLogin] = useState(false); // Neuer Zustand für die Anzeige der Login-Fehlermeldung
@@ -34,7 +41,6 @@ const LoginDialog: React.FC<LoginDialogProps> = ({ open, onClose, loginData, set
}, [open]);
// useQuery für Login
const {refetch: refetchLogin, isLoading: isLoadingLogin, error: errorLogin} = useQuery({
queryKey: ["submitLogin", loginData],
@@ -114,7 +120,8 @@ const LoginDialog: React.FC<LoginDialogProps> = ({ open, onClose, loginData, set
handleLogin();
} else {
handleRegister();
}}} noValidate>
}
}} noValidate>
<DialogTitle>{showRegister ? t("register") : t("login")}</DialogTitle>
<DialogContent>
<TextField

View File

@@ -32,9 +32,11 @@
border-radius: 4px;
background-color: rgba(255, 255, 255, 0.15);
}
.search:hover {
background-color: rgba(255, 255, 255, 0.25);
}
.search-icon-wrapper {
padding: 8px;
height: 100%;
@@ -44,6 +46,7 @@
align-items: center;
justify-content: center;
}
.search-input {
color: inherit;
width: 100%;

View File

@@ -57,7 +57,6 @@ export default function NavBar() {
.map(key => ({key, label: t(key)}));
const settings = user
? [
{

View File

@@ -1,5 +1,19 @@
import {Close, LocalShipping, ShoppingCart} from "@mui/icons-material";
import { Alert, Box, Button, Card, Divider, Grid, IconButton, Rating, Snackbar, SnackbarCloseReason, Stack, TextField, Typography } from "@mui/material";
import {
Alert,
Box,
Button,
Card,
Divider,
Grid,
IconButton,
Rating,
Snackbar,
SnackbarCloseReason,
Stack,
TextField,
Typography
} from "@mui/material";
import React, {useEffect, useState} from "react";
import {useTranslation} from "react-i18next";
import Item from "../../components/Item";
@@ -146,7 +160,8 @@ export default function ProductInfo({ item }: { item: Item }) {
{t('inStock')} ({item.stock} {t('available')})
</Alert>
) : item.stock > 0 ? (
<Alert severity="warning" variant='outlined'>{t('almostSoldOut')} ({item.stock} {t('available')})</Alert>
<Alert severity="warning"
variant='outlined'>{t('almostSoldOut')} ({item.stock} {t('available')})</Alert>
) : (
<Alert severity="error" variant='filled'>{t('outOfStock')}</Alert>
)}

View File

@@ -1,12 +1,4 @@
import {
Card,
CardActionArea,
CardContent,
Paper,
Rating,
Typography,
useTheme
} from "@mui/material";
import {Card, CardActionArea, CardContent, Paper, Rating, Typography, useTheme} from "@mui/material";
import RatingType from "../../components/Rating";
import {useTranslation} from 'react-i18next';

View File

@@ -18,6 +18,7 @@ a {
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
@@ -46,9 +47,11 @@ button {
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
@@ -59,9 +62,11 @@ button:focus-visible {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}

View File

@@ -1,15 +1,15 @@
import {
Box,
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
Divider,
Paper,
Stack,
TextField,
Typography,
Dialog,
DialogTitle,
DialogContent,
DialogActions,
} from "@mui/material";
import {useQuery} from "@tanstack/react-query";
import {useEffect, useState} from "react";

View File

@@ -1,18 +1,5 @@
import {
AccountCircle,
Category,
QueryStats,
ReceiptLong,
} from "@mui/icons-material";
import {
Box,
List,
ListItem,
ListItemButton,
ListItemIcon,
ListItemText,
useTheme,
} from "@mui/material";
import {AccountCircle, Category, QueryStats, ReceiptLong,} from "@mui/icons-material";
import {Box, List, ListItem, ListItemButton, ListItemIcon, ListItemText, useTheme,} from "@mui/material";
import {useState} from "react";
import {useTranslation} from "react-i18next";
import AccountsInfo from "../helper/adminpanel/AccountsInfo";

View File

@@ -54,15 +54,21 @@ export default function Impressum() {
</Typography>
<Typography variant="body1" sx={{color: 'text.primary', mb: 2}}>
Mit Blick auf die nachfolgend noch näher beschriebene Datenverarbeitung haben die Nutzer und Betroffenen ...
Mit Blick auf die nachfolgend noch näher beschriebene Datenverarbeitung haben die Nutzer und Betroffenen
...
</Typography>
<Box component="ul" sx={{listStyle: 'none', p: 0, m: 0}}>
<li><Typography variant="body2" sx={{ color: 'text.primary', mb: 0.5 }}> Auskunft über die verarbeiteten Daten (Art. 15 DSGVO)</Typography></li>
<li><Typography variant="body2" sx={{ color: 'text.primary', mb: 0.5 }}> Berichtigung unrichtiger Daten (Art. 16 DSGVO)</Typography></li>
<li><Typography variant="body2" sx={{ color: 'text.primary', mb: 0.5 }}> Löschung der Daten (Art. 17 DSGVO)</Typography></li>
<li><Typography variant="body2" sx={{ color: 'text.primary', mb: 0.5 }}> Einschränkung der Verarbeitung (Art. 18 DSGVO)</Typography></li>
<li><Typography variant="body2" sx={{ color: 'text.primary', mb: 0.5 }}> Datenübertragbarkeit (Art. 20 DSGVO)</Typography></li>
<li><Typography variant="body2" sx={{color: 'text.primary', mb: 0.5}}> Auskunft über die verarbeiteten
Daten (Art. 15 DSGVO)</Typography></li>
<li><Typography variant="body2" sx={{color: 'text.primary', mb: 0.5}}> Berichtigung unrichtiger Daten
(Art. 16 DSGVO)</Typography></li>
<li><Typography variant="body2" sx={{color: 'text.primary', mb: 0.5}}> Löschung der Daten (Art. 17
DSGVO)</Typography></li>
<li><Typography variant="body2" sx={{color: 'text.primary', mb: 0.5}}> Einschränkung der Verarbeitung
(Art. 18 DSGVO)</Typography></li>
<li><Typography variant="body2" sx={{color: 'text.primary', mb: 0.5}}> Datenübertragbarkeit (Art. 20
DSGVO)</Typography></li>
</Box>
<Typography variant="h6" sx={{color: 'text.primary', mt: 4, mb: 1}}>
@@ -77,7 +83,8 @@ export default function Impressum() {
jeweils in: <Typography variant="body1" sx={{ color: 'text.primary' }}>…</Typography> */}
<Typography variant="body2" sx={{color: 'text.primary', mt: 4}}>
Mehr Infos unter: <a href="https://www.cloudflare.com/privacypolicy/" target="_blank" rel="noopener noreferrer">CloudFlare Datenschutzerklärung</a>
Mehr Infos unter: <a href="https://www.cloudflare.com/privacypolicy/" target="_blank"
rel="noopener noreferrer">CloudFlare Datenschutzerklärung</a>
</Typography>
</Box>
);

View File

@@ -7,9 +7,11 @@ import ItemCard from "../helper/homepage/ItemCard";
import AddShoppingCartIcon from '@mui/icons-material/AddShoppingCart';
import farmingStation from '../assets/fscomponents/fs_components_0.png';
import { ItemWithFSImage } from "../components/Item"; "../components/Item";
import {ItemWithFSImage} from "../components/Item";
import {fetchFarmingStationItemList} from "../helper/query/Queries";
"../components/Item";
export default function FSComponents() {
const {t} = useTranslation();
const theme = useTheme();

View File

@@ -68,7 +68,8 @@ export default function Home() {
}, [location.search, categoriesFilter]);
// Filterfunktion bleibt gleich
const filteredItems: ItemWithImage[] = useMemo(() => {return items
const filteredItems: ItemWithImage[] = useMemo(() => {
return items
.filter((item) => {
const discountedPrice = item.price100 * (1 - item.discount100 / 100);
return discountedPrice >= priceRange[0] && discountedPrice <= priceRange[1];
@@ -98,10 +99,6 @@ export default function Home() {
}, [location.search]);
// Container Ref
const containerRef = useRef<HTMLDivElement>(null);

View File

@@ -1,4 +1,4 @@
import {Box, Typography, Button, useTheme} from "@mui/material";
import {Box, Button, Typography, useTheme} from "@mui/material";
import {useNavigate} from "react-router-dom";
import "./pages.css";
import {useTranslation} from "react-i18next";

View File

@@ -1,4 +1,20 @@
import { Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, Divider, List, ListItemButton, ListItemText, Paper, Stack, Tab, Tabs, Typography } from "@mui/material";
import {
Box,
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
Divider,
List,
ListItemButton,
ListItemText,
Paper,
Stack,
Tab,
Tabs,
Typography
} from "@mui/material";
import {useQuery} from "@tanstack/react-query";
import {useEffect, useState} from "react";
import {useTranslation} from "react-i18next";
@@ -100,7 +116,8 @@ export default function Orders() {
<DialogContent dividers>
{selectedOrder && (
<Stack spacing={2}>
<Typography variant="subtitle1">{`${t('orderDate')}: ${new Date(selectedOrder.time).toUTCString()}`}</Typography>
<Typography
variant="subtitle1">{`${t('orderDate')}: ${new Date(selectedOrder.time).toUTCString()}`}</Typography>
<Divider/>
<Typography variant="subtitle2">{t('orderedItems')}:</Typography>
<List dense>
@@ -112,7 +129,8 @@ export default function Orders() {
))}
</List>
<Divider/>
<Typography variant="h6">{`${t('sum')}: ${(selectedOrder.total/100).toFixed(2)}`}</Typography>
<Typography
variant="h6">{`${t('sum')}: ${(selectedOrder.total / 100).toFixed(2)}`}</Typography>
</Stack>
)}
</DialogContent>

View File

@@ -206,7 +206,8 @@ export default function Payment() {
</Typography>
{generateBasket(t, basket)}
<Divider sx={{my: 2}}/>
<Button variant="outlined" color="error" onClick={handleClearBasket} disabled={basket.length === 0}>
<Button variant="outlined" color="error" onClick={handleClearBasket}
disabled={basket.length === 0}>
{t('clearCart')}
</Button>
{generateTotal(t, basket)}

View File

@@ -1,10 +1,4 @@
import {
Box,
Button,
Container,
Divider,
Typography
} from '@mui/material';
import {Box, Button, Container, Divider, Typography} from '@mui/material';
import {useLocation, useNavigate} from 'react-router-dom';
import Item from '../components/Item';
import ProductInfo from '../helper/productpage/ProductInfo';

View File

@@ -57,6 +57,7 @@
width: 100%;
color: var(--text-color);
}
.toppad {
padding: 20px 0;
}
@@ -163,6 +164,7 @@
.rightBound {
float: right;
}
.red {
color: #F00;
}

View File

@@ -1,5 +1,5 @@
'use client';
import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react';
import React, {createContext, ReactNode, useContext, useEffect, useState} from 'react';
import {createTheme, ThemeProvider} from '@mui/material/styles';
import {CssBaseline, GlobalStyles} from '@mui/material';
import useMediaQuery from '@mui/material/useMediaQuery';
@@ -13,7 +13,8 @@ interface ThemeContextType {
const ThemeContext = createContext<ThemeContextType>({
mode: 'light',
toggleMode: () => {},
toggleMode: () => {
},
});
export const useThemeMode = () => useContext(ThemeContext);

View File

@@ -24,17 +24,29 @@ export function hsvDegToHex(h: number): string {
let r, g, b;
if (h < 60) {
r = c; g = x; b = 0;
r = c;
g = x;
b = 0;
} else if (h < 120) {
r = x; g = c; b = 0;
r = x;
g = c;
b = 0;
} else if (h < 180) {
r = 0; g = c; b = x;
r = 0;
g = c;
b = x;
} else if (h < 240) {
r = 0; g = x; b = c;
r = 0;
g = x;
b = c;
} else if (h < 300) {
r = x; g = 0; b = c;
r = x;
g = 0;
b = c;
} else {
r = c; g = 0; b = x;
r = c;
g = 0;
b = x;
}
// scale to 0-255