Add setting for date formatting

This commit is contained in:
Gimle Larpes 2025-05-31 16:10:41 +02:00
parent 0c258ee9ef
commit c260af5023
4 changed files with 147 additions and 9 deletions

View file

@ -21,7 +21,10 @@ function Time({ timestamp, fullTime, hour24Clock, dateFormatString }) {
const timeFormat = hour24Clock ? 'HH:MM' : 'hh:MM TT'; const timeFormat = hour24Clock ? 'HH:MM' : 'hh:MM TT';
formattedDate = dateFormat(date, isToday || isYesterday ? timeFormat : dateFormatString); formattedDate = dateFormat(
date,
isToday || isYesterday ? timeFormat : dateFormatString.toLowerCase()
);
if (isYesterday) { if (isYesterday) {
formattedDate = `Yesterday, ${formattedDate}`; formattedDate = `Yesterday, ${formattedDate}`;
} }

View file

@ -1,9 +1,12 @@
import React, { import React, {
ChangeEventHandler, ChangeEventHandler,
FormEventHandler,
KeyboardEventHandler, KeyboardEventHandler,
MouseEventHandler, MouseEventHandler,
useEffect,
useState, useState,
} from 'react'; } from 'react';
import dayjs from 'dayjs';
import { import {
as, as,
Box, Box,
@ -342,10 +345,105 @@ function Appearance() {
); );
} }
function SelectDateFormat() { type CustomDateFormatProps = {
// ADD TEXT INPUT AND RELATED LOGIC-- ADD LIVE PREVIEW: e.g. [formatted current date] dateFormatString: string;
setDateFormatString: (format: string) => void;
};
function CustomDateFormat({ dateFormatString, setDateFormatString }: CustomDateFormatProps) {
const [dateFormatCustom, setDateFormatCustom] = useState(dateFormatString);
useEffect(() => {
setDateFormatCustom(dateFormatString);
}, [dateFormatString]);
const handleChange: ChangeEventHandler<HTMLInputElement> = (evt) => {
const name = evt.currentTarget.value;
setDateFormatCustom(name);
};
const handleReset = () => {
setDateFormatCustom(dateFormatString);
};
const handleSubmit: FormEventHandler<HTMLFormElement> = (evt) => {
evt.preventDefault();
const target = evt.target as HTMLFormElement | undefined;
const customDateFormatInput = target?.customDateFormatInput as HTMLInputElement | undefined;
const format = customDateFormatInput?.value;
if (!format) return;
setDateFormatString(format);
};
const hasChanges = dateFormatCustom !== dateFormatString;
return (
<SettingTile
description={
<Text size="T200">
View formatting syntax on{' '}
<a
href="https://day.js.org/docs/en/display/format"
target="_blank"
rel="noreferrer noopener"
>
Day.js
</a>
.
</Text>
}
>
<Box as="form" onSubmit={handleSubmit} gap="200">
<Box grow="Yes" direction="Column">
<Input
required
name="customDateFormatInput"
value={dateFormatCustom}
onChange={handleChange}
maxLength={16}
autoComplete="off"
variant="Secondary"
radii="300"
style={{ paddingRight: config.space.S200 }}
after={
hasChanges && (
<IconButton
type="reset"
onClick={handleReset}
size="300"
radii="300"
variant="Secondary"
>
<Icon src={Icons.Cross} size="100" />
</IconButton>
)
}
/>
</Box>
<Button
size="400"
variant={hasChanges ? 'Success' : 'Secondary'}
fill={hasChanges ? 'Solid' : 'Soft'}
outlined
radii="300"
disabled={!hasChanges}
type="submit"
>
<Text size="B400">Save</Text>
</Button>
</Box>
</SettingTile>
);
}
type PresetDateFormatProps = {
dateFormatPreset: string;
handlePresetChange: (format: string) => void;
};
function PresetDateFormat({ dateFormatPreset, handlePresetChange }: PresetDateFormatProps) {
const [menuCords, setMenuCords] = useState<RectCords>(); const [menuCords, setMenuCords] = useState<RectCords>();
const [dateFormatString, setDateFormatString] = useSetting(settingsAtom, 'dateFormatString');
const dateFormatItems = useDateFormatItems(); const dateFormatItems = useDateFormatItems();
const handleMenu: MouseEventHandler<HTMLButtonElement> = (evt) => { const handleMenu: MouseEventHandler<HTMLButtonElement> = (evt) => {
@ -353,7 +451,7 @@ function SelectDateFormat() {
}; };
const handleSelect = (format: DateFormat) => { const handleSelect = (format: DateFormat) => {
setDateFormatString(format); handlePresetChange(format);
setMenuCords(undefined); setMenuCords(undefined);
}; };
@ -369,7 +467,7 @@ function SelectDateFormat() {
onClick={handleMenu} onClick={handleMenu}
> >
<Text size="T300"> <Text size="T300">
{dateFormatItems.find((i) => i.format === dateFormatString)?.name ?? dateFormatString} {dateFormatItems.find((i) => i.format === dateFormatPreset)?.name ?? dateFormatPreset}
</Text> </Text>
</Button> </Button>
<PopOut <PopOut
@ -396,7 +494,7 @@ function SelectDateFormat() {
<MenuItem <MenuItem
key={item.format} key={item.format}
size="300" size="300"
variant={dateFormatString === item.format ? 'Primary' : 'Surface'} variant={dateFormatPreset === item.format ? 'Primary' : 'Surface'}
radii="300" radii="300"
onClick={() => handleSelect(item.format)} onClick={() => handleSelect(item.format)}
> >
@ -412,6 +510,39 @@ function SelectDateFormat() {
); );
} }
function SelectDateFormat() {
const [dateFormatString, setDateFormatString] = useSetting(settingsAtom, 'dateFormatString');
const [dateFormatPreset, setDateFormatPreset] = useState(dateFormatString);
const handlePresetChange = (format: string) => {
setDateFormatPreset(format);
if (format !== '') {
setDateFormatString(format);
}
};
return (
<>
<SettingTile
title="Date Format"
description={dayjs().format(dateFormatString)}
after={
<PresetDateFormat
dateFormatPreset={dateFormatPreset}
handlePresetChange={handlePresetChange}
/>
}
/>
{dateFormatPreset === '' && (
<CustomDateFormat
dateFormatString={dateFormatString}
setDateFormatString={setDateFormatString}
/>
)}
</>
);
}
function DateAndTime() { function DateAndTime() {
const [hour24Clock, setHour24Clock] = useSetting(settingsAtom, 'hour24Clock'); const [hour24Clock, setHour24Clock] = useSetting(settingsAtom, 'hour24Clock');
@ -426,7 +557,7 @@ function DateAndTime() {
</SequenceCard> </SequenceCard>
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column"> <SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
<SettingTile title="Date Format" after={<SelectDateFormat />} /> <SelectDateFormat />
</SequenceCard> </SequenceCard>
</Box> </Box>
); );

View file

@ -17,6 +17,10 @@ export const useDateFormatItems = (): DateFormatItem[] =>
format: 'DD/MM/YYYY', format: 'DD/MM/YYYY',
name: 'DD/MM/YYYY', name: 'DD/MM/YYYY',
}, },
{
format: 'MM/DD/YYYY',
name: 'MM/DD/YYYY',
},
{ {
format: 'YYYY/MM/DD', format: 'YYYY/MM/DD',
name: 'YYYY/MM/DD', name: 'YYYY/MM/DD',

View file

@ -1,7 +1,7 @@
import { atom } from 'jotai'; import { atom } from 'jotai';
const STORAGE_KEY = 'settings'; const STORAGE_KEY = 'settings';
export type DateFormat = 'D MMM YYYY' | 'DD/MM/YYYY' | 'YYYY/MM/DD' | ''; export type DateFormat = 'D MMM YYYY' | 'DD/MM/YYYY' | 'MM/DD/YYYY' | 'YYYY/MM/DD' | '';
export type MessageSpacing = '0' | '100' | '200' | '300' | '400' | '500'; export type MessageSpacing = '0' | '100' | '200' | '300' | '400' | '500';
export enum MessageLayout { export enum MessageLayout {
Modern = 0, Modern = 0,