From b194b19a152809ce9c183f0e8596c226a2664e2c Mon Sep 17 00:00:00 2001 From: Johnny Gear Date: Sat, 7 Mar 2026 17:54:41 -0600 Subject: [PATCH] Orders Pools - Improve UI --- web/api.py | 4 + web/vite/package.json | 2 + web/vite/src/OrderSet.tsx | 5 +- web/vite/src/OrderSets.tsx | 233 +++++++++++++++++++++++-------------- web/vite/src/main.tsx | 1 + 5 files changed, 153 insertions(+), 92 deletions(-) diff --git a/web/api.py b/web/api.py index edb26ea..1084368 100644 --- a/web/api.py +++ b/web/api.py @@ -140,6 +140,8 @@ def my_order_sets(): 'punishment_pool_name': op.punishment_pool.name if op.punishment_pool is not None else None, 'orders': [{ 'id': order.id, + 'name': order.name, + 'weight': order.weight } for order in op.orders] } for op @@ -162,6 +164,8 @@ def sub_order_sets(username, sub): 'punishment_pool_name': op.punishment_pool.name if op.punishment_pool is not None else None, 'orders': [{ 'id': order.id, + 'name': order.name, + 'weight': order.weight } for order in op.orders] } for op diff --git a/web/vite/package.json b/web/vite/package.json index f18324e..d74e0ce 100644 --- a/web/vite/package.json +++ b/web/vite/package.json @@ -14,6 +14,7 @@ "vite": "^5.0.11" }, "dependencies": { + "@mantine/charts": "^8.3.13", "@mantine/core": "^8.3.12", "@mantine/dates": "^8.3.13", "@mantine/form": "^8.3.13", @@ -23,6 +24,7 @@ "react": "^19.2.3", "react-dom": "^19.2.3", "react-router": "^7.12.0", + "recharts": "^3.8.0", "typescript": "^5.9.3" } } diff --git a/web/vite/src/OrderSet.tsx b/web/vite/src/OrderSet.tsx index d8e2fb5..376c29a 100644 --- a/web/vite/src/OrderSet.tsx +++ b/web/vite/src/OrderSet.tsx @@ -113,11 +113,12 @@ export const OrderSet: React.FC = () => { } : { scheduled: false, + time: [""], orders: [], }, validate: { name: (value: string) => - value.length < 1 ? "Please enter a name" : null, + !value || value.length < 1 ? "Please enter a name" : null, time: (value: string, values: FormOrderSet) => values.scheduled && (!value || value.length < 1 || !value[0]) ? "Please set a time" @@ -281,7 +282,7 @@ export const OrderSet: React.FC = () => { label="Time" error={form.getInputProps("time").error} > - {(form.getValues().time as string[]).map((time, idx) => ( + {((form.getValues().time ?? []) as string[]).map((time, idx) => ( & { - orders: Pick; + orders: Pick; punishment_pool_name: string; })[]; username: string; @@ -56,15 +72,19 @@ export const OrderSets: React.FC = ({ const [isMastodonSet, setIsMastodonSet] = React.useState(true); React.useEffect(() => { - fetch(`/api/subs/${username}`) - .then((response) => response.json()) - .then((data) => { - if (!data.mastodon_server || !data.mastodon_username) { - setIsMastodonSet(false); - } - }); + if (username) { + fetch(`/api/subs/${username}`) + .then((response) => response.json()) + .then((data) => { + if (!data.mastodon_server || !data.mastodon_username) { + setIsMastodonSet(false); + } + }); + } }, [username]); + const [portalRef, setPortalRef] = React.useState(); + return ( <> @@ -92,90 +112,123 @@ export const OrderSets: React.FC = ({ )} - - {orderSets - ? orderSets.map( - ({ - id, - name, - scheduled, - orders, - time, - weekdays, - weekends, - probability, - punishment_pool_name, - }) => ( - - - {name} - {scheduled ? ( - <> - - Scheduled: - {time.split(",").map((time) => ( -
- -
- ))} -
- - {weekdays ? ( - Weekdays - ) : null} - {weekends ? ( - Weekends - ) : null} - {probability * 100}%} - sections={[ - { color: "cyan", value: probability * 100 }, - ]} +
{ + if (portalRef == null && node != null) { + setPortalRef(node); + } + }} + > + + {orderSets + ? orderSets.map( + ({ + id, + name, + scheduled, + orders, + time, + weekdays, + weekends, + probability, + punishment_pool_name, + }) => ( + + + {name} + {scheduled ? ( + <> + + + Scheduled: + + {time.split(",").map((time) => ( +
+ +
+ ))} +
+ + {weekdays ? ( + Weekdays + ) : null} + {weekends ? ( + Weekends + ) : null} + + {probability * 100}% + + } + sections={[ + { color: "cyan", value: probability * 100 }, + ]} + /> + + + ) : null} + {punishment_pool_name ? ( + + Punishments: {punishment_pool_name} + + ) : null} + + {orders.length > 0 ? ( + ({ + name, + value: weight, + color: + COLORS_ROTATION[idx % COLORS_ROTATION.length], + }))} + tooltipDataSource="segment" /> - - - ) : null} - - Orders: {orders.length} -
- {punishment_pool_name - ? `Punishments: ${punishment_pool_name}` - : null} -
- - handleDelete(id)} - > - - - - - Edit - + ) : null} + handleDelete(id)} + > + + + + + Edit + +
-
- - ), - ) - : null} - - - - New - - + + ), + ) + : null} + +
+ + + + New + + ); }; diff --git a/web/vite/src/main.tsx b/web/vite/src/main.tsx index 94a4a71..ec25cde 100644 --- a/web/vite/src/main.tsx +++ b/web/vite/src/main.tsx @@ -14,6 +14,7 @@ import { Notifications } from "@mantine/notifications"; import "@mantine/core/styles.css"; import "@mantine/dates/styles.css"; import "@mantine/notifications/styles.css"; +import "@mantine/charts/styles.css"; import { Dashboard, subsListLoader } from "./Dashboard"; import { SubOrderSets, subOrderSetsLoader } from "./SubOrderSets";