diff --git a/src/components/SpruceForm/Widgets/LeafyGreenWidgets.tsx b/src/components/SpruceForm/Widgets/LeafyGreenWidgets.tsx index 20fbe51099..3dd73b8d4d 100644 --- a/src/components/SpruceForm/Widgets/LeafyGreenWidgets.tsx +++ b/src/components/SpruceForm/Widgets/LeafyGreenWidgets.tsx @@ -211,6 +211,7 @@ export const LeafyGreenSelect: React.FC< export const LeafyGreenRadio: React.FC = ({ disabled, + id, label, onChange, options, @@ -224,11 +225,13 @@ export const LeafyGreenRadio: React.FC = ({ } = options; return ( + onChange(e.target.value)} - data-cy={dataCy} + value={value} > {enumOptions.map((o) => { const optionDisabled = enumDisabled?.includes(o.value) ?? false; diff --git a/src/gql/generated/types.ts b/src/gql/generated/types.ts index c75561a068..947ff4bdf0 100644 --- a/src/gql/generated/types.ts +++ b/src/gql/generated/types.ts @@ -2949,6 +2949,7 @@ export type UserSettings = { region?: Maybe; slackMemberId?: Maybe; slackUsername?: Maybe; + timeFormat?: Maybe; timezone?: Maybe; useSpruceOptions?: Maybe; }; @@ -2964,6 +2965,7 @@ export type UserSettingsInput = { region?: InputMaybe; slackMemberId?: InputMaybe; slackUsername?: InputMaybe; + timeFormat?: InputMaybe; timezone?: InputMaybe; useSpruceOptions?: InputMaybe; }; @@ -8720,6 +8722,7 @@ export type UserSettingsQuery = { region?: string | null; slackMemberId?: string | null; slackUsername?: string | null; + timeFormat?: string | null; timezone?: string | null; githubUser?: { __typename?: "GithubUser"; diff --git a/src/gql/queries/user-settings.graphql b/src/gql/queries/user-settings.graphql index 6dbaa71043..bacf7059e6 100644 --- a/src/gql/queries/user-settings.graphql +++ b/src/gql/queries/user-settings.graphql @@ -15,6 +15,7 @@ query UserSettings { region slackMemberId slackUsername + timeFormat timezone useSpruceOptions { hasUsedMainlineCommitsBefore diff --git a/src/hooks/useDateFormat.ts b/src/hooks/useDateFormat.ts index 1955c86366..4e63aa11fc 100644 --- a/src/hooks/useDateFormat.ts +++ b/src/hooks/useDateFormat.ts @@ -5,12 +5,13 @@ import { useUserTimeZone } from "./useUserTimeZone"; export const useDateFormat = () => { const timezone = useUserTimeZone(); const { userSettings } = useUserSettings(); - const { dateFormat } = userSettings || {}; + const { dateFormat, timeFormat } = userSettings || {}; return (date: string | number | Date, options: DateCopyOptions = {}) => getDateCopy(date, { tz: timezone, dateFormat, + timeFormat, ...options, }); }; diff --git a/src/pages/preferences/preferencesTabs/ProfileTab.tsx b/src/pages/preferences/preferencesTabs/ProfileTab.tsx index 26313f1164..4ac8d99f97 100644 --- a/src/pages/preferences/preferencesTabs/ProfileTab.tsx +++ b/src/pages/preferences/preferencesTabs/ProfileTab.tsx @@ -23,7 +23,13 @@ export const ProfileTab: React.FC = () => { const dispatchToast = useToastContext(); const { loading, userSettings } = useUserSettings(); - const { dateFormat, githubUser, region, timezone } = userSettings ?? {}; + const { + dateFormat, + githubUser, + region, + timeFormat = "h:mm:ss aa", + timezone, + } = userSettings ?? {}; const lastKnownAs = githubUser?.lastKnownAs || ""; const { data: awsRegionData, loading: awsRegionLoading } = @@ -49,11 +55,13 @@ export const ProfileTab: React.FC = () => { region: string; githubUser: { lastKnownAs?: string }; dateFormat: string; + timeFormat: string; }>({ timezone, region, githubUser: { lastKnownAs }, dateFormat, + timeFormat, }); useEffect(() => { @@ -62,8 +70,9 @@ export const ProfileTab: React.FC = () => { timezone, region, dateFormat, + timeFormat, }); - }, [dateFormat, githubUser, region, timezone]); + }, [dateFormat, githubUser, region, timeFormat, timezone]); const handleSubmit = () => { updateUserSettings({ @@ -111,6 +120,9 @@ export const ProfileTab: React.FC = () => { dateFormat: { "ui:placeholder": "Select a date format", }, + timeFormat: { + "ui:widget": "radio", + }, }} schema={{ properties: { @@ -150,6 +162,25 @@ export const ProfileTab: React.FC = () => { })), ], }, + timeFormat: { + type: "string", + title: "Time Format", + oneOf: [ + { + type: "string" as "string", + title: "12-hour clock", + description: "Display time with AM/PM, e.g. 12:34 PM", + enum: ["h:mm:ss aa"], + }, + + { + type: "string" as "string", + title: "24-hour clock", + description: "Use 24-hour notation, e.g. 13:34", + enum: ["H:mm:ss"], + }, + ], + }, }, }} /> diff --git a/src/utils/string/index.ts b/src/utils/string/index.ts index c2c7146177..0da8f6c62d 100644 --- a/src/utils/string/index.ts +++ b/src/utils/string/index.ts @@ -100,6 +100,7 @@ export type DateCopyOptions = { omitSeconds?: boolean; omitTimezone?: boolean; dateFormat?: string; + timeFormat?: string; }; /** @@ -111,7 +112,7 @@ export type DateCopyOptions = { * @param options.omitSeconds - if true, will not return the seconds * @param options.omitTimezone - if true, will not return the timezone * @param options.dateFormat - a date format string, such as "MMM d, yyyy" - * @returns - a string representing the date in the format of "MMM d, yyyy h:mm:ss a z" + * @returns - a string representing the date in either the user's specified format or the default, "MMM d, yyyy h:mm:ss aa z" */ export const getDateCopy = ( time: string | number | Date, @@ -121,15 +122,19 @@ export const getDateCopy = ( return ""; } const { dateOnly, omitSeconds, omitTimezone, tz } = options || {}; - let { dateFormat } = options || {}; + let { dateFormat, timeFormat } = options || {}; if (!dateFormat) { dateFormat = "MMM d, yyyy"; } + if (!timeFormat) { + timeFormat = "h:mm:ss aa"; + } + if (omitSeconds) { + timeFormat = timeFormat.replace(":ss", ""); + } const finalDateFormat = dateOnly ? dateFormat - : `${dateFormat}, h:mm${omitSeconds ? "" : ":ss"} aa${ - omitTimezone ? "" : " z" - }`; + : `${dateFormat}, ${timeFormat}${omitTimezone ? "" : " z"}`; if (tz) { return format(utcToZonedTime(time, tz), finalDateFormat, { timeZone: tz,