1
0
Fork 0

Fixed some menu stuff, and added vehicle summary

This commit is contained in:
Techognito 2025-09-05 18:06:19 +02:00
parent fc0f69dacb
commit 9c713a1be7
17 changed files with 143 additions and 24 deletions

Binary file not shown.

Binary file not shown.

View file

@ -21,7 +21,9 @@ export function App() {
<div className="app"> <div className="app">
<AppBar position="static"> <AppBar position="static">
</AppBar> </AppBar>
<StatisticsView /> <Box>
<StatisticsView />
</Box>
<YourVehicleList></YourVehicleList> <YourVehicleList></YourVehicleList>
</div> </div>
); );

View file

@ -11,7 +11,7 @@ i18n
.use(initReactI18next) .use(initReactI18next)
.init({ .init({
fallbackLng: 'en', fallbackLng: 'en',
debug: true, debug: false,
backend: { backend: {
loadPath: '/GarageApp/locales/{{lng}}/{{ns}}.json' loadPath: '/GarageApp/locales/{{lng}}/{{ns}}.json'
}, },

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -43,8 +43,35 @@ function GarageAppLogo() {
) )
} }
const pages = ['Home', 'Quick Entries', 'Import']; const pages = [
{name: 'menu.home',key: "home",href: "/"},
{name: 'menu.quickentries',key: 'quickentries',href: "/"},
{name: 'menu.import',key: 'import',href: "/"}
]
const settings = ['Profile', 'Admin', 'Logout']; const settings = ['Profile', 'Admin', 'Logout'];
//const settings = [
// {name: 'menu.settings',key: "profile",href: "/"},
// {name: 'menu.admin',key: 'admin',href: "/"},
// {name: 'menu.logout',key: 'logout',href: "/"}
//]
function MenuButtons({ key,onClick,href,name }) {
const { t, i18n } = useTranslation();
return(
<MenuItem
href={href}
key={key}
onClick={onClick}
component="a"
>
<Typography sx={{ textAlign: 'right' }}>{t (name)}</Typography>
</MenuItem>
)
}
function ResponsiveAppBar() { function ResponsiveAppBar() {
//translation //translation
const { t, i18n } = useTranslation(); const { t, i18n } = useTranslation();
@ -101,21 +128,13 @@ function ResponsiveAppBar() {
sx={{ display: { xs: 'block', md: 'none' } }} sx={{ display: { xs: 'block', md: 'none' } }}
> >
{pages.map((page) => ( {pages.map((page) => (
<MenuItem key={page} onClick={handleCloseNavMenu}> <MenuButtons key={page} onClick={page.handleCloseNavMenu} href={page.href} name={page.name} />
<Typography sx={{ textAlign: 'right' }}>{page}</Typography>
</MenuItem>
))} ))}
</Menu> </Menu>
</Box> </Box>
<Box sx={{ flexGrow: 1, display: { xs: 'none', md: 'flex' } }}> <Box sx={{ flexGrow: 1, display: { xs: 'none', md: 'flex' } }}>
{pages.map((page) => ( {pages.map((page) => (
<Button <MenuButtons key={page} onClick={page.handleCloseNavMenu} href={page.href} name={page.name} />
key={page}
onClick={handleCloseNavMenu}
sx={{ my: 2, color: 'white', display: 'block' }}
>
{page}
</Button>
))} ))}
</Box> </Box>
<Box sx={{ flexGrow: 0 }}> <Box sx={{ flexGrow: 0 }}>
@ -145,9 +164,7 @@ function ResponsiveAppBar() {
<Typography sx={{ textAlign: 'center' }}>{setting}</Typography> <Typography sx={{ textAlign: 'center' }}>{setting}</Typography>
</MenuItem> </MenuItem>
))} ))}
<MenuItem>
<MenuLanguages onClose={handleCloseUserMenu} /> <MenuLanguages onClose={handleCloseUserMenu} />
</MenuItem>
</Menu> </Menu>
</Box> </Box>
</Toolbar> </Toolbar>

View file

@ -49,7 +49,7 @@ export default function LanguageMenu( {closeAction} ) {
return ( return (
<Paper sx={{ minWidth: 320, maxWidth: '100%' }}> <Paper elevation={0} sx={{ minWidth: 320, maxWidth: '100%' }}>
<ListItemButton <ListItemButton
id="language-button" id="language-button"
aria-haspopup="listbox" aria-haspopup="listbox"

View file

@ -132,7 +132,6 @@ export default function StatisticsView() {
return ( return (
<Container> <Container>
<Box>
<Paper> <Paper>
<Grid container spacing={2} sx={{alignItems: "center",justifyContent: "space-between"}}> <Grid container spacing={2} sx={{alignItems: "center",justifyContent: "space-between"}}>
<Grid size="grow" sx={{justifyContent: "flex-start"}}> <Grid size="grow" sx={{justifyContent: "flex-start"}}>
@ -161,7 +160,6 @@ export default function StatisticsView() {
</Grid> </Grid>
</Grid> </Grid>
</Paper> </Paper>
</Box>
</Container> </Container>
); );
} }

View file

@ -0,0 +1,86 @@
import * as React from 'react';
import Grid from '@mui/material/Grid';
import Paper from '@mui/material/Paper';
import Container from '@mui/material/Container';
import { useTranslation, withTranslation, Trans } from 'react-i18next';
const uid = "39e9009e-50e1-4277-bbf7-69e5e0f6c6dc"
async function DataFetch(url) {
const response = await fetch(url);
const data = await response.json();
return data;
}
function VehicleCardSummary({ vehicleid }) {
const { t, i18n } = useTranslation();
const [data, setData] = React.useState(null);
const [loading, setLoading] = React.useState(true);
const [error, setError] = React.useState(null);
React.useEffect(() => {
async function fetchData() {
try {
const data = await DataFetch(`/GarageApp/api/fillups/${uid}/${vehicleid}/lastfillup`);
setData(data);
setLoading(false);
} catch (error) {
setError(error);
setLoading(false);
}
}
fetchData();
}, []);
console.log("blablambpmgpoa")
console.log(data)
if (loading) {
return <div>Loading...</div>;
}
if (error) {
return <div>Error: {error.message}</div>;
}
if (!data.toString()) {
return <p>Nothing Registered</p>
}
return (
<div>
<Grid container spacing={2}>
<Grid size={4}>
<Paper>
<p>{t ('lastfillup')}:</p>
</Paper>
</Grid>
<Grid size="grow">
<Paper>
{data.map((f) => (
<div>
<p>{f.date.split(" ",1)}</p>
<p>{f.total_amount.toFixed(2) + " " + f.currency}</p>
<p>{f.fuel_quantity.toFixed(2) + " @ " + f.per_unit_price.toFixed(2)}"</p>
</div>
))}
</Paper>
</Grid>
</Grid>
<Grid container spacing={2}>
<Grid size={4}>
<Paper>
<p>{t ('odometer')}:</p>
</Paper>
</Grid>
<Grid size="grow">
<Paper>
<p>{data.map((fillup) => (
<p>{fillup.odo_reading + " km"}</p>
))}</p>
</Paper>
</Grid>
</Grid>
</div>
);
}
export default VehicleCardSummary;

View file

@ -17,10 +17,12 @@ import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import MoreVertIcon from '@mui/icons-material/MoreVert'; import MoreVertIcon from '@mui/icons-material/MoreVert';
import GasStation from './icons/gasFillup' import GasStation from './icons/gasFillup'
import Expense from './icons/Expense' import Expense from './icons/Expense'
import VehicleCardSummary from "./VehicleCardSummary";
import { useTranslation, withTranslation, Trans } from 'react-i18next'; import { useTranslation, withTranslation, Trans } from 'react-i18next';
interface ExpandMoreProps extends IconButtonProps { interface ExpandMoreProps extends IconButtonProps {
expand: boolean; expand: boolean;
} }
@ -50,7 +52,7 @@ const ExpandMore = styled((props: ExpandMoreProps) => {
], ],
})); }));
export default function VehicleCard({ nickname, makemodel, registration}) { export default function VehicleCard({ nickname, makemodel, registration, vehicleID}) {
const { t, i18n } = useTranslation(); const { t, i18n } = useTranslation();
const [expanded, setExpanded] = React.useState(false); const [expanded, setExpanded] = React.useState(false);
@ -93,9 +95,7 @@ export default function VehicleCard({ nickname, makemodel, registration}) {
</CardActions> </CardActions>
<Collapse in={expanded} timeout="auto" unmountOnExit> <Collapse in={expanded} timeout="auto" unmountOnExit>
<CardContent> <CardContent>
<Typography> <VehicleCardSummary vehicleid={vehicleID} />
Expanded area
</Typography>
</CardContent> </CardContent>
</Collapse> </Collapse>
</Card> </Card>

View file

@ -5,9 +5,16 @@ import VehicleCard from "./VehicleCards";
import Button from '@mui/material/Button'; import Button from '@mui/material/Button';
import { useTranslation, withTranslation, Trans } from 'react-i18next'; import { useTranslation, withTranslation, Trans } from 'react-i18next';
const uid = "39e9009e-50e1-4277-bbf7-69e5e0f6c6dc" const uid = "39e9009e-50e1-4277-bbf7-69e5e0f6c6dc"
const response = await fetch(`/GarageApp/api/vehicles/${uid}`); const response = await fetch(`/GarageApp/api/vehicles/${uid}`);
const vehicles = await response.json(); const vehicles = await response.json();
export default function YourVehicleList() { export default function YourVehicleList() {
const { t, i18n } = useTranslation(); const { t, i18n } = useTranslation();
return ( return (
@ -29,7 +36,7 @@ export default function YourVehicleList() {
}}> }}>
{vehicles.map((vehicle, index) => ( {vehicles.map((vehicle, index) => (
<Grid key={index} size={{ xs: 2, sm: 4, md: 4 }} justifyContent="center" alignItems="center"> <Grid key={index} size={{ xs: 2, sm: 4, md: 4 }} justifyContent="center" alignItems="center">
<VehicleCard nickname={vehicle.nickname} makemodel={vehicle.make + " " + vehicle.model} registration={vehicle.registration}/> <VehicleCard nickname={vehicle.nickname} makemodel={vehicle.make + " " + vehicle.model} registration={vehicle.registration} vehicleID={vehicle.id}/>
</Grid> </Grid>
))} ))}
</Grid> </Grid>

View file

@ -26,7 +26,6 @@ const server = serve({
return new Response(Bun.file(path)) return new Response(Bun.file(path))
}, },
"/GarageApp/api/vehicles/:uid": async req => { "/GarageApp/api/vehicles/:uid": async req => {
//const uid = "39e9009e-50e1-4277-bbf7-69e5e0f6c6dc"
const uid = req.params.uid; const uid = req.params.uid;
const query = db.query( const query = db.query(
`SELECT * FROM vehicles WHERE id IN (SELECT vehicle_id FROM user_vehicles WHERE user_id='${uid}');` `SELECT * FROM vehicles WHERE id IN (SELECT vehicle_id FROM user_vehicles WHERE user_id='${uid}');`
@ -53,6 +52,16 @@ const server = serve({
return Response.json(fillups) return Response.json(fillups)
}, },
"/GarageApp/api/fillups/:uid/:vid/lastfillup": async req => {
const uid = req.params.uid;
const vid = req.params.vid;
const query = db.query(
`SELECT * FROM fillups WHERE user_id='${uid}' AND vehicle_id='${vid}' ORDER BY odo_reading DESC LIMIT 1;`
);
const lastfillup = query.all();
return Response.json(lastfillup)
},
"/api/hello": { "/api/hello": {
async GET(req) { async GET(req) {