Skip to content

Commit 8942c8a

Browse files
committed
chore: add custom MonthPicker
1 parent 4174115 commit 8942c8a

File tree

10 files changed

+40
-23
lines changed

10 files changed

+40
-23
lines changed

apps/frontend/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
"@quassel/ui": "workspace:*",
2424
"@tanstack/react-query": "^5.62.0",
2525
"@tanstack/react-router": "^1.85.0",
26-
"dayjs": "^1.11.13",
2726
"nanostores": "^0.11.3",
2827
"openapi-fetch": "^0.13.1",
2928
"openapi-react-query": "^0.2.6",

apps/frontend/src/components/questionnaire/PeriodForm.tsx

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { useForm } from "@mantine/form";
22
import { Button, Flex, MonthPicker, Stack, TextInput } from "@quassel/ui";
33
import { i18n } from "../../stores/i18n";
44
import { useStore } from "@nanostores/react";
5-
import dayjs from "dayjs";
65
import { useEffect } from "react";
76

87
export type PeriodFormValues = {
@@ -16,7 +15,7 @@ type PeriodFormProps = {
1615
actionLabel: string;
1716
};
1817

19-
export const messages = i18n("periodForm", {
18+
const messages = i18n("periodForm", {
2019
labelTitle: "Title",
2120
});
2221

@@ -25,11 +24,7 @@ export function PeriodForm({ onSave, actionLabel, period }: PeriodFormProps) {
2524

2625
const f = useForm<PeriodFormValues>({
2726
initialValues: period,
28-
transformValues(values) {
29-
values.range[1] = dayjs(values.range[1]).utc().endOf("month").toDate();
30-
31-
return values;
32-
},
27+
mode: "uncontrolled",
3328
});
3429

3530
useEffect(() => {
@@ -43,7 +38,7 @@ export function PeriodForm({ onSave, actionLabel, period }: PeriodFormProps) {
4338
<form onSubmit={f.onSubmit((values) => onSave(values))}>
4439
<Stack>
4540
<Flex justify="center">
46-
<MonthPicker {...f.getInputProps("range")} size="md" type="range" numberOfColumns={2} />
41+
<MonthPicker {...f.getInputProps("range")} size="md" type="range" numberOfColumns={2} selectEndOfMonth />
4742
</Flex>
4843
<TextInput {...f.getInputProps("title")} label={t.labelTitle} />
4944
<Button type="submit">{actionLabel}</Button>

apps/frontend/src/main.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import { ThemeProvider } from "@quassel/ui";
55
import { RouterProvider, createRouter } from "@tanstack/react-router";
66
import { routeTree } from "./routeTree.gen.ts";
77
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
8-
import dayjs from "dayjs";
9-
import utc from "dayjs/plugin/utc";
108

119
const queryClient = new QueryClient();
1210
const router = createRouter({ routeTree, context: { queryClient }, defaultPreload: "intent", defaultPreloadStaleTime: 0 });
@@ -17,8 +15,6 @@ declare module "@tanstack/react-router" {
1715
}
1816
}
1917

20-
dayjs.extend(utc);
21-
2218
createRoot(document.getElementById("root")!).render(
2319
<StrictMode>
2420
<QueryClientProvider client={queryClient}>

apps/frontend/src/routes/_auth/questionnaire/_questionnaire/new.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { PeriodForm, PeriodFormValues } from "../../../../components/questionnai
55
import { $api } from "../../../../stores/api";
66
import { $questionnaire } from "../../../../stores/questionnaire";
77

8-
export const messages = i18n("questionnaireNew", {
8+
const messages = i18n("questionnaireNew", {
99
title: "Create new period of life",
1010
formAction: "Create",
1111
});

libs/ui/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"@mantine/dates": "^7.14.3",
3131
"@mantine/hooks": "^7.14.3",
3232
"@tabler/icons-react": "3.17.0",
33+
"dayjs": "^1.11.13",
3334
"react": "^18.3.1",
3435
"react-dom": "^18.3.1"
3536
},
Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,29 @@
1-
import { MonthPicker as MantineMonthPicker, MonthPickerProps as MantineMonthPickerProps } from "@mantine/dates";
1+
import {
2+
DatePickerType,
3+
DatesRangeValue,
4+
DateValue,
5+
MonthPicker as MantineMonthPicker,
6+
MonthPickerProps as MantineMonthPickerProps,
7+
} from "@mantine/dates";
8+
import dayjs from "dayjs";
29

3-
type MonthPickerProps = MantineMonthPickerProps;
10+
interface MonthPickerProps<Type extends DatePickerType = "default"> extends MantineMonthPickerProps<Type> {
11+
selectEndOfMonth?: boolean;
12+
}
13+
14+
function isRangeValue(date: DateValue | DatesRangeValue | Date[]): date is DatesRangeValue {
15+
return Array.isArray(date) && date.length === 2;
16+
}
17+
18+
export function MonthPicker<Type extends DatePickerType = "default">({ selectEndOfMonth, ...rest }: MonthPickerProps<Type>) {
19+
const onChange: MonthPickerProps<Type>["onChange"] = (date) => {
20+
if (rest.type === "range" && isRangeValue(date) && selectEndOfMonth) {
21+
const [start, end] = date;
22+
const newDate = [start, dayjs(end).utc().endOf("month").toDate()];
23+
date = newDate as typeof date;
24+
}
25+
rest.onChange!(date);
26+
};
427

5-
export function MonthPicker(props: MonthPickerProps) {
6-
return <MantineMonthPicker {...props} />;
28+
return <MantineMonthPicker {...rest} onChange={rest.onChange ? onChange : undefined} />;
729
}

libs/ui/src/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export { ThemeProvider } from "./theme/ThemeProvider";
3333

3434
// custom components
3535
export { Brand } from "./components/Brand";
36+
export { MonthPicker } from "./components/MonthPicker";
3637

3738
// external components
3839
export {
@@ -57,8 +58,6 @@ export {
5758
useMantineTheme,
5859
} from "@mantine/core";
5960

60-
export { MonthPicker } from "@mantine/dates";
61-
6261
export {
6362
IconLogout,
6463
IconUsers,

libs/ui/src/theme/ThemeProvider.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import { MantineProvider, MantineThemeOverride, MantineProviderProps } from "@mantine/core";
22
import "./Theme.css";
33
import { DatesProvider } from "@mantine/dates";
4+
import dayjs from "dayjs";
5+
import utc from "dayjs/plugin/utc";
46

7+
dayjs.extend(utc);
58
type ThemeProviderProps = MantineProviderProps;
69

710
export const theme: MantineThemeOverride = {

libs/ui/vite.config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ export default defineConfig({
1717
external: ["react", "react-dom"],
1818
output: {
1919
globals: {
20+
dayjs: "dayjs",
21+
"dayjs/plugin/utc": "dayjsPluginUtc",
2022
react: "React",
2123
"react/jsx-runtime": "jsxRuntime",
2224
"@mantine/core": "mantineCore",

pnpm-lock.yaml

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)