Skip to content

Commit

Permalink
vinvoor: add a settings page
Browse files Browse the repository at this point in the history
  • Loading branch information
Topvennie committed Jul 18, 2024
1 parent b07f8ed commit da46acc
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 13 deletions.
2 changes: 1 addition & 1 deletion vingo/handlers/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func (Settings) Update(c *fiber.Ctx) error {
sess.Set(STORE_USER, &user)
sess.Save()

return c.SendStatus(200)
return c.Status(200).JSON(map[string]bool{})
}

func (Settings) Get(c *fiber.Ctx) error {
Expand Down
7 changes: 3 additions & 4 deletions vinvoor/src/cards/CardsTableBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,9 @@ export const CardsTableBody: FC<CardsTableBodyProps> = ({
(cards) => setCards(cards)
);
})
.catch((error) => {
enqueueSnackbar(nameSaveFailure, { variant: "error" });
console.log(error);
});
.catch(() =>
enqueueSnackbar(nameSaveFailure, { variant: "error" })
);
})
.catch(() => {}); // Required otherwise the confirm dialog will throw an error in the console
};
Expand Down
1 change: 0 additions & 1 deletion vinvoor/src/leaderboard/LeaderboardTableBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ const getPositionChange = (positionChange: number) => {
const getPosition = (position: number) => {
switch (position) {
case 1:
// return <PodiumGold htmlColor="#FFD700" />;
return (
<Icon>
<img src={FirstPlaceIcon} />
Expand Down
5 changes: 3 additions & 2 deletions vinvoor/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { Cards } from "./cards/Cards.tsx";
import { ErrorPage } from "./errors/ErrorPage.tsx";
import { Leaderboard } from "./leaderboard/Leaderboard.tsx";
import { Scans } from "./scans/Scans.tsx";
import { SettingsOverview } from "./settings/SettingsOverview.tsx";
import { ThemeProvider } from "./theme/ThemeProvider";
import { Login } from "./user/Login.tsx";
import { Logout } from "./user/Logout.tsx";
Expand Down Expand Up @@ -47,8 +48,8 @@ const router = createBrowserRouter([
},
{
path: "settings",

}
element: <SettingsOverview />,
},
],
},
]);
Expand Down
9 changes: 6 additions & 3 deletions vinvoor/src/navbar/NavBar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import LeaderboardIcon from "@mui/icons-material/Leaderboard";
import { LeaderboardOutlined } from "@mui/icons-material";
import { AppBar, Box, Container, Toolbar } from "@mui/material";
import {
CogOutline,
CreditCardMultipleOutline,
CreditCardScanOutline,
} from "mdi-material-ui";
Expand All @@ -20,10 +21,12 @@ export interface PageIcon {
const navBarPages: PageIcon[] = [
{ page: "Scans", icon: <CreditCardScanOutline sx={{ mr: ".3rem" }} /> },
{ page: "Cards", icon: <CreditCardMultipleOutline sx={{ mr: ".3rem" }} /> },
{ page: "Leaderboard", icon: <LeaderboardIcon sx={{ mr: ".3rem" }} /> },
{ page: "Leaderboard", icon: <LeaderboardOutlined sx={{ mr: ".3rem" }} /> },
];

const userMenuPages: PageIcon[] = [];
const userMenuPages: PageIcon[] = [
{ page: "Settings", icon: <CogOutline sx={{ mr: ".3rem" }} /> },
];

export const NavBar = () => {
const {
Expand Down
Empty file removed vinvoor/src/settings/Settings.tsx
Empty file.
170 changes: 170 additions & 0 deletions vinvoor/src/settings/SettingsOverview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import {
Box,
Button,
Checkbox,
FormControl,
FormControlLabel,
Grid,
Paper,
Tooltip,
Typography,
} from "@mui/material";
import { useConfirm } from "material-ui-confirm";
import { HelpCircleOutline } from "mdi-material-ui";
import { useSnackbar } from "notistack";
import { ChangeEvent, useState } from "react";
import { LoadingSkeleton } from "../components/LoadingSkeleton";
import { useFetch } from "../hooks/useFetch";
import {
adjustableSettings,
converSettingsJSON,
Settings,
} from "../types/settings";
import { patchApi } from "../util/fetch";

const defaultSettings: Settings = {
id: -1,
createdAt: new Date(),
scanInOut: false,
leaderboard: false,
public: false,
};

const saveSuccess = "Settings saved successfully";
const saveFailure = "Unable to save settings";
const handleDeleteContent = (
<Box>
<Typography gutterBottom>
Are you sure you want to delete all your data?
</Typography>
<Typography variant="h5" color="error" mb={5}>
This is irreversible!
</Typography>
</Box>
);

export const SettingsOverview = () => {
const [settings, setSettings] = useState<Settings>(defaultSettings);
const { loading } = useFetch<Settings>(
"settings",
setSettings,
converSettingsJSON
);
const { enqueueSnackbar } = useSnackbar();
const confirm = useConfirm();

const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setSettings({
...settings,
[event.target.name]: event.target.checked,
});
};

const handleSubmit = () => {
patchApi("settings", {
scanInOut: settings.scanInOut,
leaderboard: settings.leaderboard,
public: settings.public,
})
.then(() => enqueueSnackbar(saveSuccess, { variant: "success" }))
.catch((error) => enqueueSnackbar(error, { variant: "error" }));
};

const handleDelete = () => {
confirm({
title: "Delete data",
content: handleDeleteContent,
acknowledgement: "Delete all my data",
confirmationText: "Delete",
confirmationButtonProps: { color: "error" },
})
.then(() =>
enqueueSnackbar("This is not possible yet", {
variant: "error",
})
)
.catch(() => {});
};

return (
<LoadingSkeleton loading={loading}>
<Grid
container
alignItems="stretch"
justifyContent="space-between"
columnSpacing={4}
rowSpacing={1}
>
<Grid item xs={6}>
<Paper elevation={4} sx={{ p: "10px" }}>
<FormControl>
{adjustableSettings.map((setting) => (
<FormControlLabel
value="end"
control={
<Checkbox
checked={
settings[setting.id] as boolean
}
onChange={handleChange}
name={setting.id}
/>
}
label={
<Box display="flex">
<Typography>
{setting.name}
</Typography>
<Tooltip
title={setting.description}
placement="right"
>
<HelpCircleOutline
sx={{
fontSize: "15px",
ml: ".3rem",
}}
/>
</Tooltip>
</Box>
}
key={setting.id}
/>
))}
</FormControl>
</Paper>
</Grid>
<Grid item xs={6}>
<Paper elevation={4} sx={{ p: "10px", height: "100%" }}>
<Box
display="flex"
alignItems="center"
justifyContent="center"
height="100%"
width="100%"
>
<Typography variant="body2">
More settings coming soon!
</Typography>
</Box>
</Paper>
</Grid>
<Grid item xs={12} sx={{ mt: "1rem" }}>
<Button variant="outlined" fullWidth onClick={handleSubmit}>
Save
</Button>
</Grid>
<Grid item xs={12}>
<Button
variant="outlined"
fullWidth
color="error"
onClick={handleDelete}
>
Delete data
</Button>
</Grid>
</Grid>
</LoadingSkeleton>
);
};
46 changes: 46 additions & 0 deletions vinvoor/src/types/settings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Base, BaseJSON } from "./general";

interface SettingsJSON extends BaseJSON {
scanInOut: boolean;
leaderboard: boolean;
public: boolean;
}

export interface Settings extends Base {
scanInOut: boolean;
leaderboard: boolean;
public: boolean;
}

export const converSettingsJSON = (settingsJSON: SettingsJSON): Settings => ({
id: settingsJSON.id,
createdAt: new Date(settingsJSON.createdAt),
scanInOut: settingsJSON.scanInOut,
leaderboard: settingsJSON.leaderboard,
public: settingsJSON.public,
});

interface AdjustableSettings {
id: keyof Settings;
name: string;
description: string;
}

export const adjustableSettings: AdjustableSettings[] = [
{
id: "scanInOut",
name: "Scan in and out",
description:
"A second scan on the same day will be interpreted as a scan out",
},
{
id: "leaderboard",
name: "Leaderboard",
description: "Show yourself on the leaderboard",
},
{
id: "public",
name: "Public",
description: "Let others see you!",
},
];
4 changes: 2 additions & 2 deletions vinvoor/src/util/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const getApi = <T>(endpoint: string, convertData?: (data: any) => T) => {

export const postApi = <T>(
endpoint: string,
body: { [key: string]: string } = {}
body: { [key: string]: string | number | boolean } = {}
) => {
return _fetch<T>(`${URLS.API}/${endpoint}`, {
method: "POST",
Expand All @@ -20,7 +20,7 @@ export const postApi = <T>(

export const patchApi = <T>(
endpoint: string,
body: { [key: string]: string } = {}
body: { [key: string]: string | number | boolean } = {}
) => {
return _fetch<T>(`${URLS.API}/${endpoint}`, {
method: "PATCH",
Expand Down

0 comments on commit da46acc

Please sign in to comment.