mirror of
https://github.com/lukevella/rallly.git
synced 2025-07-17 08:17:26 +02:00
116 lines
3.4 KiB
TypeScript
116 lines
3.4 KiB
TypeScript
import { cn } from "@rallly/ui";
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogDescription,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
DialogTrigger,
|
|
} from "@rallly/ui/dialog";
|
|
import { Label } from "@rallly/ui/label";
|
|
import dayjs from "dayjs";
|
|
import { GlobeIcon } from "lucide-react";
|
|
import React from "react";
|
|
import { useInterval } from "react-use";
|
|
import spacetime from "spacetime";
|
|
import soft from "timezone-soft";
|
|
|
|
import { TimeFormatPicker } from "@/components/time-format-picker";
|
|
import { TimeZoneSelect } from "@/components/time-zone-picker/time-zone-select";
|
|
import { Trans } from "@/components/trans";
|
|
import { usePreferences } from "@/contexts/preferences";
|
|
import { useDayjs } from "@/utils/dayjs";
|
|
|
|
export const TimePreferences = () => {
|
|
const { updatePreferences } = usePreferences();
|
|
const { timeFormat, timeZone } = useDayjs();
|
|
|
|
return (
|
|
<div className="grid gap-4">
|
|
<div className="grid gap-2">
|
|
<Label>
|
|
<Trans i18nKey="timeZone" />
|
|
</Label>
|
|
<TimeZoneSelect
|
|
value={timeZone}
|
|
onValueChange={(newTimeZone) => {
|
|
updatePreferences({ timeZone: newTimeZone });
|
|
}}
|
|
/>
|
|
</div>
|
|
<div className="grid gap-2">
|
|
<Label>
|
|
<Trans i18nKey="timeFormat" />
|
|
</Label>
|
|
<TimeFormatPicker
|
|
value={timeFormat}
|
|
onChange={(newTimeFormat) => {
|
|
updatePreferences({ timeFormat: newTimeFormat });
|
|
}}
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const Clock = ({ className }: { className?: string }) => {
|
|
const { timeZone, timeFormat } = useDayjs();
|
|
const timeZoneDisplayFormat = soft(timeZone)[0];
|
|
const now = spacetime.now(timeZone);
|
|
const standardAbbrev = timeZoneDisplayFormat.standard.abbr;
|
|
const dstAbbrev = timeZoneDisplayFormat.daylight?.abbr;
|
|
const abbrev = now.isDST() ? dstAbbrev : standardAbbrev;
|
|
const [time, setTime] = React.useState(new Date());
|
|
useInterval(() => {
|
|
setTime(new Date());
|
|
}, 1000);
|
|
|
|
return (
|
|
<span
|
|
key={timeFormat}
|
|
className={cn("inline-block font-medium tabular-nums", className)}
|
|
>{`${dayjs(time).tz(timeZone).format("LT")} ${abbrev}`}</span>
|
|
);
|
|
};
|
|
|
|
export const TimesShownIn = () => {
|
|
const { timeZone } = useDayjs();
|
|
|
|
return (
|
|
<ClockPreferences>
|
|
<button className="inline-flex items-center gap-x-2.5 text-sm hover:underline">
|
|
<GlobeIcon className="size-4" />
|
|
<Trans
|
|
i18nKey="timeShownIn"
|
|
defaults="Times shown in {timeZone}"
|
|
values={{ timeZone: timeZone.replaceAll("_", " ") }}
|
|
/>
|
|
</button>
|
|
</ClockPreferences>
|
|
);
|
|
};
|
|
|
|
export const ClockPreferences = ({ children }: React.PropsWithChildren) => {
|
|
return (
|
|
<Dialog modal={false}>
|
|
<DialogTrigger asChild>{children}</DialogTrigger>
|
|
<DialogContent className="sm:max-w-sm">
|
|
<DialogHeader>
|
|
<DialogTitle>
|
|
<Trans i18nKey="clockPreferences" defaults="Clock Preferences" />
|
|
</DialogTitle>
|
|
<DialogDescription>
|
|
<Trans
|
|
i18nKey="clockPreferencesDescription"
|
|
defaults="Set your preferred time zone and time format."
|
|
/>
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
<div className="bg-muted grid h-24 items-center justify-center rounded-md text-2xl font-bold">
|
|
<Clock />
|
|
</div>
|
|
<TimePreferences />
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
};
|