UI improvements
This commit is contained in:
parent
058891dc36
commit
14009ad6d3
5 changed files with 152 additions and 114 deletions
|
|
@ -90,7 +90,7 @@ def sub_order_set(username, set_id):
|
||||||
|
|
||||||
update_add_ons(order_to_update, updated_order['add_ons'])
|
update_add_ons(order_to_update, updated_order['add_ons'])
|
||||||
else:
|
else:
|
||||||
Order.create(
|
order_to_update = Order.create(
|
||||||
pool=op,
|
pool=op,
|
||||||
name=updated_order['name'],
|
name=updated_order['name'],
|
||||||
weight=updated_order['weight'],
|
weight=updated_order['weight'],
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mantine/core": "^8.3.12",
|
"@mantine/core": "^8.3.12",
|
||||||
"@mantine/form": "^8.3.13",
|
"@mantine/form": "^8.3.13",
|
||||||
|
"@mantine/notifications": "^8.3.13",
|
||||||
"@tabler/icons-react": "^3.36.1",
|
"@tabler/icons-react": "^3.36.1",
|
||||||
"postcss": "^8.5.6",
|
"postcss": "^8.5.6",
|
||||||
"react": "^19.2.3",
|
"react": "^19.2.3",
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,23 @@ import {
|
||||||
Slider,
|
Slider,
|
||||||
TextInput,
|
TextInput,
|
||||||
Button,
|
Button,
|
||||||
Divider,
|
|
||||||
Flex,
|
Flex,
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
|
Title,
|
||||||
|
Box,
|
||||||
|
Affix,
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
|
import { notifications } from "@mantine/notifications";
|
||||||
import { randomId } from "@mantine/hooks";
|
import { randomId } from "@mantine/hooks";
|
||||||
import { useForm } from "@mantine/form";
|
import { useForm } from "@mantine/form";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Params, useLoaderData, useParams, useNavigate } from "react-router";
|
import {
|
||||||
|
Params,
|
||||||
|
useLoaderData,
|
||||||
|
useParams,
|
||||||
|
useNavigate,
|
||||||
|
Link,
|
||||||
|
} from "react-router";
|
||||||
import { IconMinus, IconPlus } from "@tabler/icons-react";
|
import { IconMinus, IconPlus } from "@tabler/icons-react";
|
||||||
|
|
||||||
export const subOrderSetLoader = async ({
|
export const subOrderSetLoader = async ({
|
||||||
|
|
@ -21,7 +30,7 @@ export const subOrderSetLoader = async ({
|
||||||
params: Params<string>;
|
params: Params<string>;
|
||||||
}) =>
|
}) =>
|
||||||
fetch(`/api/subs/${username}/sets/${set_id}`).then((response) =>
|
fetch(`/api/subs/${username}/sets/${set_id}`).then((response) =>
|
||||||
response.json()
|
response.json(),
|
||||||
);
|
);
|
||||||
|
|
||||||
type FormOrderSetOrderAddOn = Omit<OrderSetOrderAddOn, "id"> & {
|
type FormOrderSetOrderAddOn = Omit<OrderSetOrderAddOn, "id"> & {
|
||||||
|
|
@ -48,11 +57,14 @@ export const SubOrderSet: React.FC = () => {
|
||||||
mode: "uncontrolled",
|
mode: "uncontrolled",
|
||||||
initialValues: { id, name, orders },
|
initialValues: { id, name, orders },
|
||||||
validate: {
|
validate: {
|
||||||
name: (value) => (value.length < 1 ? "Please enter a name" : null),
|
name: (value: string) =>
|
||||||
|
value.length < 1 ? "Please enter a name" : null,
|
||||||
orders: {
|
orders: {
|
||||||
name: (value) => (value.length < 1 ? "Please enter a name" : null),
|
name: (value: string) =>
|
||||||
|
value.length < 1 ? "Please enter a name" : null,
|
||||||
add_ons: {
|
add_ons: {
|
||||||
name: (value) => (value.length < 1 ? "Please enter a name" : null),
|
name: (value: string) =>
|
||||||
|
value.length < 1 ? "Please enter a name" : null,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -68,13 +80,23 @@ export const SubOrderSet: React.FC = () => {
|
||||||
body: JSON.stringify(values),
|
body: JSON.stringify(values),
|
||||||
}).then((response) => {
|
}).then((response) => {
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
|
notifications.show({
|
||||||
|
title: "Success",
|
||||||
|
message: `Updates to ${values.name} were successful`,
|
||||||
|
color: "green",
|
||||||
|
});
|
||||||
navigate(`/dashboard/subs/${username}`);
|
navigate(`/dashboard/subs/${username}`);
|
||||||
} else {
|
} else {
|
||||||
|
notifications.show({
|
||||||
|
title: "Error",
|
||||||
|
message: "There was a problem with your request",
|
||||||
|
color: "red",
|
||||||
|
});
|
||||||
console.error(response.statusText);
|
console.error(response.statusText);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
[form]
|
[form],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleNewOrder = React.useCallback(() => {
|
const handleNewOrder = React.useCallback(() => {
|
||||||
|
|
@ -97,7 +119,7 @@ export const SubOrderSet: React.FC = () => {
|
||||||
form.setFieldValue(`orders.${idx}._delete`, true);
|
form.setFieldValue(`orders.${idx}._delete`, true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[form]
|
[form],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleNewAddOn = React.useCallback(
|
const handleNewAddOn = React.useCallback(
|
||||||
|
|
@ -108,7 +130,7 @@ export const SubOrderSet: React.FC = () => {
|
||||||
probability: 0.5,
|
probability: 0.5,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[form]
|
[form],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleRemoveAddOn = React.useCallback(
|
const handleRemoveAddOn = React.useCallback(
|
||||||
|
|
@ -123,15 +145,20 @@ export const SubOrderSet: React.FC = () => {
|
||||||
form.setFieldValue(`orders.${idx}.add_ons.${add_on_idx}._delete`, true);
|
form.setFieldValue(`orders.${idx}.add_ons.${add_on_idx}._delete`, true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[form]
|
[form],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit}>
|
|
||||||
<Container pb="xl">
|
<Container pb="xl">
|
||||||
<h1>{name}</h1>
|
<Box mb="lg">
|
||||||
<>
|
<Title order={1}>{name}</Title>
|
||||||
|
<Link to={`/dashboard/subs/${username}`}>Return to {username}</Link>
|
||||||
|
</Box>
|
||||||
|
<form id="order-set" onSubmit={handleSubmit}>
|
||||||
<TextInput {...form.getInputProps("name")} label="Name" />
|
<TextInput {...form.getInputProps("name")} label="Name" />
|
||||||
|
<Title order={2} mt="lg" mb="sm">
|
||||||
|
Orders
|
||||||
|
</Title>
|
||||||
{form.getValues().orders.map(({ id: order_id, _delete }, idx) =>
|
{form.getValues().orders.map(({ id: order_id, _delete }, idx) =>
|
||||||
_delete ? null : (
|
_delete ? null : (
|
||||||
<Paper key={order_id} bg="gray.2">
|
<Paper key={order_id} bg="gray.2">
|
||||||
|
|
@ -167,39 +194,45 @@ export const SubOrderSet: React.FC = () => {
|
||||||
step={0.05}
|
step={0.05}
|
||||||
/>
|
/>
|
||||||
</Input.Wrapper>
|
</Input.Wrapper>
|
||||||
<h4>Add-On</h4>
|
<Paper p="xs">
|
||||||
|
<Title order={4} mb="sm">
|
||||||
|
Add-Ons
|
||||||
|
</Title>
|
||||||
{form
|
{form
|
||||||
.getValues()
|
.getValues()
|
||||||
.orders[idx].add_ons.map(
|
.orders[
|
||||||
({ id: add_on_id, _delete: _add_on_delete }, add_on_idx) =>
|
idx
|
||||||
|
].add_ons.map(({ id: add_on_id, _delete: _add_on_delete }, add_on_idx) =>
|
||||||
_add_on_delete ? null : (
|
_add_on_delete ? null : (
|
||||||
<Paper key={add_on_id} p="xs">
|
<Flex
|
||||||
<Flex gap="xl" justify="space-between">
|
key={add_on_id}
|
||||||
|
gap="xl"
|
||||||
|
align="center"
|
||||||
|
justify="space-between"
|
||||||
|
>
|
||||||
<TextInput
|
<TextInput
|
||||||
{...form.getInputProps(
|
{...form.getInputProps(
|
||||||
`orders.${idx}.add_ons.${add_on_idx}.name`
|
`orders.${idx}.add_ons.${add_on_idx}.name`,
|
||||||
)}
|
)}
|
||||||
label="Name"
|
|
||||||
/>
|
/>
|
||||||
|
<Input.Wrapper flex={1}>
|
||||||
|
<Slider
|
||||||
|
{...form.getInputProps(
|
||||||
|
`orders.${idx}.add_ons.${add_on_idx}.probability`,
|
||||||
|
)}
|
||||||
|
domain={[0, 1]}
|
||||||
|
step={0.05}
|
||||||
|
/>
|
||||||
|
</Input.Wrapper>
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
color="red.8"
|
color="red.8"
|
||||||
|
mt="-8px"
|
||||||
onClick={() => handleRemoveAddOn(idx, add_on_idx)}
|
onClick={() => handleRemoveAddOn(idx, add_on_idx)}
|
||||||
>
|
>
|
||||||
<IconMinus />
|
<IconMinus />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Input.Wrapper label="Probability">
|
),
|
||||||
<Slider
|
|
||||||
{...form.getInputProps(
|
|
||||||
`orders.${idx}.add_ons.${add_on_idx}.probability`
|
|
||||||
)}
|
|
||||||
name="Probability"
|
|
||||||
domain={[0, 1]}
|
|
||||||
step={0.05}
|
|
||||||
/>
|
|
||||||
</Input.Wrapper>
|
|
||||||
</Paper>
|
|
||||||
)
|
|
||||||
)}
|
)}
|
||||||
<Button onClick={() => handleNewAddOn(idx)}>
|
<Button onClick={() => handleNewAddOn(idx)}>
|
||||||
<IconPlus
|
<IconPlus
|
||||||
|
|
@ -209,18 +242,26 @@ export const SubOrderSet: React.FC = () => {
|
||||||
New Add On
|
New Add On
|
||||||
</Button>
|
</Button>
|
||||||
</Paper>
|
</Paper>
|
||||||
)
|
</Paper>
|
||||||
|
),
|
||||||
)}
|
)}
|
||||||
<Button onClick={handleNewOrder}>
|
<Button onClick={handleNewOrder}>
|
||||||
<IconPlus style={{ width: "60%", height: "60%" }} stroke={2} />
|
<IconPlus style={{ width: "60%", height: "60%" }} stroke={2} />
|
||||||
New Order
|
New Order
|
||||||
</Button>
|
</Button>
|
||||||
<Divider my="md" />
|
<Box my="40px" />
|
||||||
|
<Affix position={{ bottom: 0 }} w="100%">
|
||||||
|
<Paper mb={0} bg="gray.1">
|
||||||
|
<Container>
|
||||||
<Flex justify="flex-end">
|
<Flex justify="flex-end">
|
||||||
<Button type="submit">Save</Button>
|
<Button type="submit" form="order-set">
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
</Flex>
|
</Flex>
|
||||||
</>
|
|
||||||
</Container>
|
</Container>
|
||||||
|
</Paper>
|
||||||
|
</Affix>
|
||||||
</form>
|
</form>
|
||||||
|
</Container>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,4 @@
|
||||||
import {
|
import { Container, Title } from "@mantine/core";
|
||||||
Container,
|
|
||||||
Accordion,
|
|
||||||
TextInput,
|
|
||||||
Divider,
|
|
||||||
Input,
|
|
||||||
Slider,
|
|
||||||
} from "@mantine/core";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Link, Params, useLoaderData, useParams } from "react-router";
|
import { Link, Params, useLoaderData, useParams } from "react-router";
|
||||||
|
|
||||||
|
|
@ -27,8 +20,9 @@ export const SubOrderSets: React.FC = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<h1>Orders for {sub_username}</h1>
|
<Title order={1} mb="lg">
|
||||||
<Accordion>
|
Orders for {sub_username}
|
||||||
|
</Title>
|
||||||
{orders
|
{orders
|
||||||
? orders.map(({ id, name }) => (
|
? orders.map(({ id, name }) => (
|
||||||
<Link key={id} to={`/dashboard/subs/${sub_username}/${id}`}>
|
<Link key={id} to={`/dashboard/subs/${sub_username}/${id}`}>
|
||||||
|
|
@ -36,7 +30,6 @@ export const SubOrderSets: React.FC = () => {
|
||||||
</Link>
|
</Link>
|
||||||
))
|
))
|
||||||
: null}
|
: null}
|
||||||
</Accordion>
|
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,10 @@ import {
|
||||||
Paper,
|
Paper,
|
||||||
Slider,
|
Slider,
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
|
import { Notifications } from "@mantine/notifications";
|
||||||
|
|
||||||
import "@mantine/core/styles.css";
|
import "@mantine/core/styles.css";
|
||||||
|
import "@mantine/notifications/styles.css";
|
||||||
|
|
||||||
import { SubsList, subsListLoader } from "./SubsList";
|
import { SubsList, subsListLoader } from "./SubsList";
|
||||||
import { SubOrderSets, subOrderSetsLoader } from "./SubOrderSets";
|
import { SubOrderSets, subOrderSetsLoader } from "./SubOrderSets";
|
||||||
|
|
@ -37,7 +39,7 @@ const theme = createTheme({
|
||||||
root: {
|
root: {
|
||||||
"--slider-track-bg": theme.colors.gray[4],
|
"--slider-track-bg": theme.colors.gray[4],
|
||||||
},
|
},
|
||||||
} as any),
|
}) as any,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
@ -63,7 +65,8 @@ const router = createBrowserRouter([
|
||||||
ReactDOM.createRoot(document.getElementById("root")!).render(
|
ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<MantineProvider theme={theme}>
|
<MantineProvider theme={theme}>
|
||||||
|
<Notifications />
|
||||||
<RouterProvider router={router} />
|
<RouterProvider router={router} />
|
||||||
</MantineProvider>
|
</MantineProvider>
|
||||||
</React.StrictMode>
|
</React.StrictMode>,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue