From 4c5c8bec045537dbb76af95a58e315b552421183 Mon Sep 17 00:00:00 2001 From: John Groszko Date: Tue, 7 Apr 2026 18:46:38 -0500 Subject: [PATCH] Dark theme --- db/queries.py | 4 +- web/vite/src/ConfirmDialogButton.tsx | 18 ++++- web/vite/src/Dashboard.tsx | 10 +-- web/vite/src/Header.tsx | 17 +++-- web/vite/src/OrderSet.tsx | 11 ++- web/vite/src/OrderSets.tsx | 33 ++++----- web/vite/src/Profile.tsx | 7 +- web/vite/src/ProfileVerification.tsx | 2 +- web/vite/src/SubOrderSets.tsx | 8 +- web/vite/src/TimelineList.tsx | 105 ++++++++++++++------------- web/vite/src/main.tsx | 13 +++- web/vite/src/theme.ts | 78 ++++++++++++++++++++ 12 files changed, 209 insertions(+), 97 deletions(-) create mode 100644 web/vite/src/theme.ts diff --git a/db/queries.py b/db/queries.py index 8e37e20..5fa7f4f 100644 --- a/db/queries.py +++ b/db/queries.py @@ -186,7 +186,7 @@ def timeline_event_put(type, text, user, orders_pool=None, order_status=None, ac extra=json.dumps(extra) if extra is not None else None ) -def timeline_event_recent(user_ids, actor_ids=None): +def timeline_event_recent(user_ids, actor_ids=None, limit=5): return (TimelineEvent .select() .where(( @@ -194,5 +194,5 @@ def timeline_event_recent(user_ids, actor_ids=None): (TimelineEvent.actor_user_id.in_(actor_ids) if actor_ids is not None else True) )) .order_by(TimelineEvent.updated_at.desc()) - .limit(10) + .limit(limit) ) \ No newline at end of file diff --git a/web/vite/src/ConfirmDialogButton.tsx b/web/vite/src/ConfirmDialogButton.tsx index 55faa2f..c2b321a 100644 --- a/web/vite/src/ConfirmDialogButton.tsx +++ b/web/vite/src/ConfirmDialogButton.tsx @@ -1,7 +1,7 @@ import React from "react"; import { useDisclosure } from "@mantine/hooks"; -import { Button, Modal, Text, Flex } from "@mantine/core"; +import { Button, Modal, Text, Flex, ButtonVariant } from "@mantine/core"; export const ConfirmDialogButton: React.FC<{ text: string; @@ -9,7 +9,15 @@ export const ConfirmDialogButton: React.FC<{ buttonColor: string; onConfirm: () => void; children: React.ReactNode; -}> = ({ text, buttonText, buttonColor, onConfirm, children }) => { + variant?: ButtonVariant; +}> = ({ + text, + buttonText, + buttonColor, + onConfirm, + children, + variant = "filled", +}) => { const [opened, { open, close }] = useDisclosure(); const handleConfirm = React.useCallback(() => { @@ -22,13 +30,15 @@ export const ConfirmDialogButton: React.FC<{ {text} - + - diff --git a/web/vite/src/Dashboard.tsx b/web/vite/src/Dashboard.tsx index 5fb5637..efa6b1b 100644 --- a/web/vite/src/Dashboard.tsx +++ b/web/vite/src/Dashboard.tsx @@ -25,15 +25,7 @@ const SubsList: React.FC = ({ subs }) => ( {subs.map(({ sub_username, telegram_photo_url }) => ( - + {telegram_photo_url ? ( { const { username, telegram_photo_url } = useUserContext(); @@ -14,12 +21,12 @@ export const Header: React.FC = () => { return ( - + - {username} + {username} - + diff --git a/web/vite/src/OrderSet.tsx b/web/vite/src/OrderSet.tsx index 376c29a..1c0cf0b 100644 --- a/web/vite/src/OrderSet.tsx +++ b/web/vite/src/OrderSet.tsx @@ -16,6 +16,7 @@ import { NumberInput, Text, Select, + Anchor, } from "@mantine/core"; import { notifications } from "@mantine/notifications"; import { TimeInput } from "@mantine/dates"; @@ -248,7 +249,9 @@ export const OrderSet: React.FC = () => { <> {orderSet?.name || "New Order Set"} - Return to {username} + + Return to {username} +
@@ -259,7 +262,7 @@ export const OrderSet: React.FC = () => { mt="lg" /> - + { {form.getValues().orders.map(({ id: order_id, _delete }, idx) => _delete ? null : ( - + { - + diff --git a/web/vite/src/ProfileVerification.tsx b/web/vite/src/ProfileVerification.tsx index c3f98dd..37c830e 100644 --- a/web/vite/src/ProfileVerification.tsx +++ b/web/vite/src/ProfileVerification.tsx @@ -75,7 +75,7 @@ export const ProfileVerification: React.FC = ({ ); return ( - + Order Verification diff --git a/web/vite/src/SubOrderSets.tsx b/web/vite/src/SubOrderSets.tsx index c660573..74890f3 100644 --- a/web/vite/src/SubOrderSets.tsx +++ b/web/vite/src/SubOrderSets.tsx @@ -2,7 +2,7 @@ import React from "react"; import { Params, useLoaderData, useParams, Link } from "react-router"; import { OrderSetProps, OrderSets } from "./OrderSets"; import { ProfileVerification } from "./ProfileVerification"; -import { Title } from "@mantine/core"; +import { Anchor, Title } from "@mantine/core"; export const subOrderSetsLoader = async ({ params: { username }, @@ -26,7 +26,11 @@ export const SubOrderSets: React.FC = () => { <OrderSets username={sub_username} orderSets={orderSets} - linkBack={<Link to={`/dashboard/`}>Return to dashboard</Link>} + linkBack={ + <Anchor component={Link} to={`/dashboard/`}> + Return to dashboard + </Anchor> + } /> {profile ? ( <> diff --git a/web/vite/src/TimelineList.tsx b/web/vite/src/TimelineList.tsx index b1b12fc..874b397 100644 --- a/web/vite/src/TimelineList.tsx +++ b/web/vite/src/TimelineList.tsx @@ -1,4 +1,4 @@ -import { Timeline, Text, Title, Box, Flex } from "@mantine/core"; +import { Timeline, Text, Title, Box, Flex, Card, Anchor } from "@mantine/core"; import React from "react"; import moment from "moment"; import { Link } from "react-router"; @@ -65,55 +65,60 @@ export const TimelineList: React.FC<{ <Title order={1} mb="lg"> Timeline - - {timeline.map( - ({ - id, - updated_at, - type, - text, - username, - actor_username, - orders_pool, - extra, - }) => ( - - - {text.split("\n").map((str, idx) => ( - - {str} -
-
- ))} -
- - {extra?.mastodon_status_url ? ( - - - Mastodon Post - - - ) : null} - {orders_pool ? ( - - - {orders_pool.name} - - - ) : null} - {actor_username ? ( - - {actor_username} - - ) : null} - - {username} + + + {timeline.map( + ({ + id, + updated_at, + type, + text, + username, + actor_username, + orders_pool, + extra, + }) => ( + + + {text.split("\n").map((str, idx) => ( + + {str} +
+
+ ))}
- {moment(updated_at).fromNow()} -
-
- ), - )} -
+ + {extra?.mastodon_status_url ? ( + + + Mastodon Post + + + ) : null} + {orders_pool ? ( + + + {orders_pool.name} + + + ) : null} + {actor_username ? ( + + {actor_username} + + ) : null} + + {username} + + {moment(updated_at).fromNow()} + + + ), + )} + +
); diff --git a/web/vite/src/main.tsx b/web/vite/src/main.tsx index ec25cde..67372b0 100644 --- a/web/vite/src/main.tsx +++ b/web/vite/src/main.tsx @@ -8,9 +8,13 @@ import { Input, Paper, Slider, + Image, + mergeThemeOverrides, } from "@mantine/core"; import { Notifications } from "@mantine/notifications"; +import { mantineTheme } from "./theme"; + import "@mantine/core/styles.css"; import "@mantine/dates/styles.css"; import "@mantine/notifications/styles.css"; @@ -46,6 +50,11 @@ const theme = createTheme({ }, }) as any, }), + Image: Image.extend({ + defaultProps: { + radius: "xs", + }, + }), }, }); @@ -83,9 +92,11 @@ const router = createBrowserRouter([ }, ]); +const mergedTheme = mergeThemeOverrides(mantineTheme, theme); + ReactDOM.createRoot(document.getElementById("root")!).render( - + diff --git a/web/vite/src/theme.ts b/web/vite/src/theme.ts new file mode 100644 index 0000000..84d413a --- /dev/null +++ b/web/vite/src/theme.ts @@ -0,0 +1,78 @@ +import { Card, Container, createTheme, Paper, rem, Select } from "@mantine/core"; +import type { MantineThemeOverride } from "@mantine/core"; + +const CONTAINER_SIZES: Record = { + xxs: rem("200px"), + xs: rem("300px"), + sm: rem("400px"), + md: rem("500px"), + lg: rem("600px"), + xl: rem("1400px"), + xxl: rem("1600px"), +}; + +export const mantineTheme: MantineThemeOverride = createTheme({ + /** Put your mantine theme override here */ + fontSizes: { + xs: rem("12px"), + sm: rem("14px"), + md: rem("16px"), + lg: rem("18px"), + xl: rem("20px"), + "2xl": rem("24px"), + "3xl": rem("30px"), + "4xl": rem("36px"), + "5xl": rem("48px"), + }, + spacing: { + "3xs": rem("4px"), + "2xs": rem("8px"), + xs: rem("10px"), + sm: rem("12px"), + md: rem("16px"), + lg: rem("20px"), + xl: rem("24px"), + "2xl": rem("28px"), + "3xl": rem("32px"), + }, + primaryColor: "orange", + components: { + /** Put your mantine component override here */ + Container: Container.extend({ + vars: (_, { size, fluid }) => ({ + root: { + "--container-size": fluid + ? "100%" + : size !== undefined && size in CONTAINER_SIZES + ? CONTAINER_SIZES[size] + : rem(size), + }, + }), + }), + Paper: Paper.extend({ + defaultProps: { + p: "md", + shadow: "xl", + radius: "md", + withBorder: true, + }, + }), + + Card: Card.extend({ + defaultProps: { + p: "xl", + shadow: "xl", + radius: "var(--mantine-radius-default)", + withBorder: true, + }, + }), + Select: Select.extend({ + defaultProps: { + checkIconPosition: "right", + }, + }), + }, + other: { + style: "mantine", + }, +});