From e5af638219031ba6aaa87c9cc00120efee7e8e72 Mon Sep 17 00:00:00 2001 From: Nevo David Date: Thu, 7 Aug 2025 20:34:31 +0700 Subject: [PATCH] feat: change timezone and date format --- apps/frontend/src/app/(app)/layout.tsx | 8 ++ .../src/components/analytics/chart.tsx | 3 +- .../billing/main.billing.component.tsx | 3 +- .../components/launches/calendar.context.tsx | 11 +-- .../src/components/launches/calendar.tsx | 23 +++--- .../src/components/launches/filters.tsx | 13 +-- .../launches/helpers/date.picker.tsx | 7 +- .../launches/helpers/isuscitizen.utils.tsx | 4 +- .../launches/helpers/use.integration.ts | 3 +- .../src/components/launches/time.table.tsx | 5 +- .../components/layout/continue.provider.tsx | 3 +- .../src/components/layout/set.timezone.tsx | 41 ++++++++++ .../components/layout/settings.component.tsx | 20 ++--- .../marketplace/special.message.tsx | 3 +- .../src/components/messages/messages.tsx | 3 +- .../components/new-launch/add.edit.modal.tsx | 3 +- .../src/components/new-launch/store.ts | 3 +- .../post-url-selector/post.url.selector.tsx | 7 +- apps/frontend/src/components/sets/sets.tsx | 3 +- .../components/settings/global.settings.tsx | 21 +++++ .../components/settings/metric.component.tsx | 70 ++++++++++++++++ .../settings/settings.component.tsx | 80 ------------------- .../standalone-modal/standalone.modal.tsx | 3 +- .../translation/locales/en/translation.json | 1 + package.json | 1 + pnpm-lock.yaml | 8 ++ 26 files changed, 216 insertions(+), 134 deletions(-) create mode 100644 apps/frontend/src/components/layout/set.timezone.tsx create mode 100644 apps/frontend/src/components/settings/global.settings.tsx create mode 100644 apps/frontend/src/components/settings/metric.component.tsx delete mode 100644 apps/frontend/src/components/settings/settings.component.tsx diff --git a/apps/frontend/src/app/(app)/layout.tsx b/apps/frontend/src/app/(app)/layout.tsx index 6d14032a..e30d05f2 100644 --- a/apps/frontend/src/app/(app)/layout.tsx +++ b/apps/frontend/src/app/(app)/layout.tsx @@ -18,6 +18,13 @@ import { FacebookComponent } from '@gitroom/frontend/components/layout/facebook. import { headers } from 'next/headers'; import { headerName } from '@gitroom/react/translation/i18n.config'; import { HtmlComponent } from '@gitroom/frontend/components/layout/html.component'; +import dynamicLoad from 'next/dynamic'; +const SetTimezone = dynamicLoad( + () => import('@gitroom/frontend/components/layout/set.timezone'), + { + ssr: false, + } +); const jakartaSans = Plus_Jakarta_Sans({ weight: ['600', '500'], @@ -72,6 +79,7 @@ export default async function AppLayout({ children }: { children: ReactNode }) { } > + diff --git a/apps/frontend/src/components/analytics/chart.tsx b/apps/frontend/src/components/analytics/chart.tsx index 27f3253b..be2ccf43 100644 --- a/apps/frontend/src/components/analytics/chart.tsx +++ b/apps/frontend/src/components/analytics/chart.tsx @@ -7,6 +7,7 @@ import { StarsList, } from '@gitroom/frontend/components/analytics/stars.and.forks.interface'; import dayjs from 'dayjs'; +import { newDayjs } from '@gitroom/frontend/components/layout/set.timezone'; export const Chart: FC<{ list: StarsList[] | ForksList[]; }> = (props) => { @@ -48,7 +49,7 @@ export const Chart: FC<{ }, }, data: { - labels: list.map((row) => dayjs(row.date).format('DD/MM/YYYY')), + labels: list.map((row) => newDayjs(row.date).format('DD/MM/YYYY')), datasets: [ { borderColor: '#fff', diff --git a/apps/frontend/src/components/billing/main.billing.component.tsx b/apps/frontend/src/components/billing/main.billing.component.tsx index 4012d38d..00476764 100644 --- a/apps/frontend/src/components/billing/main.billing.component.tsx +++ b/apps/frontend/src/components/billing/main.billing.component.tsx @@ -28,6 +28,7 @@ import { TrackEnum } from '@gitroom/nestjs-libraries/user/track.enum'; import { PurchaseCrypto } from '@gitroom/frontend/components/billing/purchase.crypto'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; import { FinishTrial } from '@gitroom/frontend/components/billing/finish.trial'; +import { newDayjs } from '@gitroom/frontend/components/layout/set.timezone'; export const Prorate: FC<{ period: 'MONTHLY' | 'YEARLY'; @@ -505,7 +506,7 @@ export const MainBillingComponent: FC<{ 'your_subscription_will_be_canceled_at', 'Your subscription will be canceled at' )} - {dayjs(subscription.cancelAt).local().format('D MMM, YYYY')} + {newDayjs(subscription.cancelAt).local().format('D MMM, YYYY')}
{t( 'you_will_never_be_charged_again', diff --git a/apps/frontend/src/components/launches/calendar.context.tsx b/apps/frontend/src/components/launches/calendar.context.tsx index 7ecdf006..02725198 100644 --- a/apps/frontend/src/components/launches/calendar.context.tsx +++ b/apps/frontend/src/components/launches/calendar.context.tsx @@ -20,12 +20,13 @@ import isoWeek from 'dayjs/plugin/isoWeek'; import weekOfYear from 'dayjs/plugin/weekOfYear'; import { extend } from 'dayjs'; import useCookie from 'react-use-cookie'; +import { newDayjs } from '@gitroom/frontend/components/layout/set.timezone'; extend(isoWeek); extend(weekOfYear); export const CalendarContext = createContext({ - startDate: dayjs().startOf('isoWeek').format('YYYY-MM-DD'), - endDate: dayjs().endOf('isoWeek').format('YYYY-MM-DD'), + startDate: newDayjs().startOf('isoWeek').format('YYYY-MM-DD'), + endDate: newDayjs().endOf('isoWeek').format('YYYY-MM-DD'), customer: null as string | null, sets: [] as { name: string; id: string; content: string[] }[], signature: undefined as any, @@ -86,7 +87,7 @@ export interface Integrations { // Helper function to get start and end dates based on display type function getDateRange(display: string, referenceDate?: string) { - const date = referenceDate ? dayjs(referenceDate) : dayjs(); + const date = referenceDate ? newDayjs(referenceDate) : newDayjs(); switch (display) { case 'day': @@ -153,8 +154,8 @@ export const CalendarWeekProvider: FC<{ const modifiedParams = new URLSearchParams({ display: filters.display, customer: filters?.customer?.toString() || '', - startDate: dayjs(filters.startDate).startOf('day').utc().format(), - endDate: dayjs(filters.endDate).endOf('day').utc().format(), + startDate: newDayjs(filters.startDate).startOf('day').utc().format(), + endDate: newDayjs(filters.endDate).endOf('day').utc().format(), }).toString(); const data = (await fetch(`/posts?${modifiedParams}`)).json(); diff --git a/apps/frontend/src/components/launches/calendar.tsx b/apps/frontend/src/components/launches/calendar.tsx index 98a95063..9c2720bf 100644 --- a/apps/frontend/src/components/launches/calendar.tsx +++ b/apps/frontend/src/components/launches/calendar.tsx @@ -54,6 +54,7 @@ import { deleteDialog } from '@gitroom/react/helpers/delete.dialog'; import { useVariables } from '@gitroom/react/helpers/variable.context'; import { stripHtmlValidation } from '@gitroom/helpers/utils/strip.html.validation'; import { ModalWrapperComponent } from '../new-launch/modal.wrapper.component'; +import { newDayjs } from '@gitroom/frontend/components/layout/set.timezone'; // Extend dayjs with necessary plugins extend(isSameOrAfter); @@ -146,7 +147,7 @@ export const DayView = () => { {options.map((option) => (
- {dayjs() + {newDayjs() .utc() .startOf('day') .add(option[0].time, 'minute') @@ -186,7 +187,7 @@ export const WeekView = () => { dayjs.locale(currentLanguage); const days = []; - const weekStart = dayjs(startDate); + const weekStart = newDayjs(startDate); for (let i = 0; i < 7; i++) { const day = weekStart.add(i, 'day'); days.push({ @@ -214,10 +215,10 @@ export const WeekView = () => {
- {day.day === dayjs().format('L') && ( + {day.day === newDayjs().format('L') && (
)} {day.day} @@ -259,17 +260,17 @@ export const MonthView = () => { const days = []; // Starting from Monday (1) to Sunday (7) for (let i = 1; i <= 7; i++) { - days.push(dayjs().day(i).format('dddd')); + days.push(newDayjs().day(i).format('dddd')); } return days; }, [i18next.resolvedLanguage]); const calendarDays = useMemo(() => { - const monthStart = dayjs(startDate); + const monthStart = newDayjs(startDate); const currentMonth = monthStart.month(); const currentYear = monthStart.year(); - const startOfMonth = dayjs(new Date(currentYear, currentMonth, 1)); + const startOfMonth = newDayjs(new Date(currentYear, currentMonth, 1)); // Calculate the day offset for Monday (isoWeekday() returns 1 for Monday) const startDayOfWeek = startOfMonth.isoWeekday(); // 1 for Monday, 7 for Sunday @@ -314,7 +315,7 @@ export const MonthView = () => { className="text-center items-center justify-center flex min-h-[100px]" >
@@ -390,7 +391,7 @@ export const CalendarColumn: FC<{ const isBeforeNow = useMemo(() => { const originalUtc = getDate.startOf('hour'); - return originalUtc.startOf('hour').isBefore(dayjs().startOf('hour').utc()); + return originalUtc.startOf('hour').isBefore(newDayjs().startOf('hour').utc()); }, [getDate, num]); const { start, stop } = useInterval( @@ -571,8 +572,8 @@ export const CalendarColumn: FC<{ randomHour ? getDate.hour(Math.floor(Math.random() * 24)) : getDate.format('YYYY-MM-DDTHH:mm:ss') === - dayjs().startOf('hour').format('YYYY-MM-DDTHH:mm:ss') - ? dayjs().add(10, 'minute') + newDayjs().startOf('hour').format('YYYY-MM-DDTHH:mm:ss') + ? newDayjs().add(10, 'minute') : getDate } {...(set?.content ? { set: JSON.parse(set.content) } : {})} diff --git a/apps/frontend/src/components/launches/filters.tsx b/apps/frontend/src/components/launches/filters.tsx index 048e66de..6980cbc4 100644 --- a/apps/frontend/src/components/launches/filters.tsx +++ b/apps/frontend/src/components/launches/filters.tsx @@ -7,13 +7,14 @@ import { useCallback } from 'react'; import { SelectCustomer } from '@gitroom/frontend/components/launches/select.customer'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; import i18next from 'i18next'; +import { newDayjs } from '@gitroom/frontend/components/layout/set.timezone'; // Helper function to get start and end dates based on display type function getDateRange( display: 'day' | 'week' | 'month', referenceDate?: string ) { - const date = referenceDate ? dayjs(referenceDate) : dayjs(); + const date = referenceDate ? newDayjs(referenceDate) : newDayjs(); switch (display) { case 'day': @@ -44,8 +45,8 @@ export const Filters = () => { // Calculate display date range text const getDisplayText = () => { - const startDate = dayjs(calendar.startDate); - const endDate = dayjs(calendar.endDate); + const startDate = newDayjs(calendar.startDate); + const endDate = newDayjs(calendar.endDate); switch (calendar.display) { case 'day': @@ -60,7 +61,7 @@ export const Filters = () => { }; const setToday = useCallback(() => { - const today = dayjs(); + const today = newDayjs(); const currentRange = getDateRange( calendar.display as 'day' | 'week' | 'month' ); @@ -151,7 +152,7 @@ export const Filters = () => { ); const next = useCallback(() => { - const currentStart = dayjs(calendar.startDate); + const currentStart = newDayjs(calendar.startDate); let nextStart: dayjs.Dayjs; switch (calendar.display) { @@ -181,7 +182,7 @@ export const Filters = () => { }, [calendar]); const previous = useCallback(() => { - const currentStart = dayjs(calendar.startDate); + const currentStart = newDayjs(calendar.startDate); let prevStart: dayjs.Dayjs; switch (calendar.display) { diff --git a/apps/frontend/src/components/launches/helpers/date.picker.tsx b/apps/frontend/src/components/launches/helpers/date.picker.tsx index 54505c3f..2d4b2831 100644 --- a/apps/frontend/src/components/launches/helpers/date.picker.tsx +++ b/apps/frontend/src/components/launches/helpers/date.picker.tsx @@ -5,6 +5,7 @@ import { useClickOutside } from '@mantine/hooks'; import { Button } from '@gitroom/react/form/button'; import { isUSCitizen } from './isuscitizen.utils'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; +import { newDayjs } from '@gitroom/frontend/components/layout/set.timezone'; export const DatePicker: FC<{ date: dayjs.Dayjs; onChange: (day: dayjs.Dayjs) => void; @@ -22,10 +23,10 @@ export const DatePicker: FC<{ const changeDate = useCallback( (type: 'date' | 'time') => (day: Date) => { onChange( - dayjs( + newDayjs( type === 'time' - ? date.format('YYYY-MM-DD') + ' ' + dayjs(day).format('HH:mm:ss') - : dayjs(day).format('YYYY-MM-DD') + ' ' + date.format('HH:mm:ss') + ? date.format('YYYY-MM-DD') + ' ' + newDayjs(day).format('HH:mm:ss') + : newDayjs(day).format('YYYY-MM-DD') + ' ' + date.format('HH:mm:ss') ) ); }, diff --git a/apps/frontend/src/components/launches/helpers/isuscitizen.utils.tsx b/apps/frontend/src/components/launches/helpers/isuscitizen.utils.tsx index b33afc48..706d8032 100644 --- a/apps/frontend/src/components/launches/helpers/isuscitizen.utils.tsx +++ b/apps/frontend/src/components/launches/helpers/isuscitizen.utils.tsx @@ -1,4 +1,4 @@ export const isUSCitizen = () => { - const userLanguage = navigator.language || navigator.languages[0]; - return userLanguage.startsWith('en-US'); + const userLanguage = localStorage.getItem('isUS') || ((navigator.language || navigator.languages[0]).startsWith('en-US') ? 'US' : 'GLOBAL'); + return userLanguage === 'US'; }; diff --git a/apps/frontend/src/components/launches/helpers/use.integration.ts b/apps/frontend/src/components/launches/helpers/use.integration.ts index 9341b7fb..265431f5 100644 --- a/apps/frontend/src/components/launches/helpers/use.integration.ts +++ b/apps/frontend/src/components/launches/helpers/use.integration.ts @@ -3,6 +3,7 @@ import { createContext, useContext } from 'react'; import { Integrations } from '@gitroom/frontend/components/launches/calendar.context'; import dayjs from 'dayjs'; +import { newDayjs } from '@gitroom/frontend/components/layout/set.timezone'; export const IntegrationContext = createContext<{ date: dayjs.Dayjs; integration: Integrations | undefined; @@ -18,7 +19,7 @@ export const IntegrationContext = createContext<{ }>({ integration: undefined, value: [], - date: dayjs(), + date: newDayjs(), allIntegrations: [], }); export const useIntegration = () => useContext(IntegrationContext); diff --git a/apps/frontend/src/components/launches/time.table.tsx b/apps/frontend/src/components/launches/time.table.tsx index 7963b1df..e5b98f36 100644 --- a/apps/frontend/src/components/launches/time.table.tsx +++ b/apps/frontend/src/components/launches/time.table.tsx @@ -14,6 +14,7 @@ import { useModals } from '@mantine/modals'; import { sortBy } from 'lodash'; import { usePreventWindowUnload } from '@gitroom/react/helpers/use.prevent.window.unload'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; +import { newDayjs } from '@gitroom/frontend/components/layout/set.timezone'; dayjs.extend(utc); dayjs.extend(timezone); const hours = [...Array(24).keys()].map((i, index) => ({ @@ -70,12 +71,12 @@ export const TimeTable: FC<{ ); const addHour = useCallback(() => { const calculateMinutes = - dayjs() + newDayjs() .utc() .startOf('day') .add(hour, 'hours') .add(minute, 'minutes') - .diff(dayjs().utc().startOf('day'), 'minutes') - dayjs.tz().utcOffset(); + .diff(newDayjs().utc().startOf('day'), 'minutes') - dayjs.tz().utcOffset(); setCurrentTimes((prev) => [ ...prev, { diff --git a/apps/frontend/src/components/layout/continue.provider.tsx b/apps/frontend/src/components/layout/continue.provider.tsx index 38a1fa7b..46d7f9c8 100644 --- a/apps/frontend/src/components/layout/continue.provider.tsx +++ b/apps/frontend/src/components/layout/continue.provider.tsx @@ -6,6 +6,7 @@ import dayjs from 'dayjs'; import useSWR, { useSWRConfig } from 'swr'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; import { continueProviderList } from '@gitroom/frontend/components/new-launch/providers/continue-provider/list'; +import { newDayjs } from '@gitroom/frontend/components/layout/set.timezone'; export const Null: FC<{ closeModal: () => void; existingId: string[]; @@ -82,7 +83,7 @@ export const ContinueProvider: FC = () => {
{ + return localStorage.getItem('timezone') || dayjs.tz.guess(); +}; + +export const newDayjs = (config?: ConfigType) => { + return dayjs.tz(config, getTimezone()); +}; + +const SetTimezone: FC = () => { + useEffect(() => { + if (localStorage.getItem('timezone')) { + dayjs.tz.setDefault(getTimezone()); + } + }, []); + return null; +}; + +export default SetTimezone; diff --git a/apps/frontend/src/components/layout/settings.component.tsx b/apps/frontend/src/components/layout/settings.component.tsx index ac43dc8b..514bcc37 100644 --- a/apps/frontend/src/components/layout/settings.component.tsx +++ b/apps/frontend/src/components/layout/settings.component.tsx @@ -30,6 +30,7 @@ import { SignaturesComponent } from '@gitroom/frontend/components/settings/signa import { Autopost } from '@gitroom/frontend/components/autopost/autopost'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; import { SVGLine } from '@gitroom/frontend/components/launches/launches.component'; +import { GlobalSettings } from '@gitroom/frontend/components/settings/global.settings'; export const SettingsPopup: FC<{ getRef?: Ref; }> = (props) => { @@ -80,22 +81,12 @@ export const SettingsPopup: FC<{ close(); }, []); - const [tab, setTab] = useState(() => { - if (user?.tier?.team_members && isGeneral) { - return 'teams'; - } - if (user?.tier?.webhooks) { - return 'webhooks'; - } - if (user?.tier?.autoPost) { - return 'autopost'; - } - return 'sets'; - }); + const [tab, setTab] = useState('global_settings'); const t = useT(); const list = useMemo(() => { const arr = []; + arr.push({ tab: 'global_settings', label: t('global_settings', 'Global Settings') }); // Populate tabs based on user permissions if (user?.tier?.team_members && isGeneral) { arr.push({ tab: 'teams', label: t('teams', 'Teams') }); @@ -168,6 +159,11 @@ export const SettingsPopup: FC<{ !getRef && 'rounded-[4px]' )} > + {tab === 'global_settings' && ( +
+ +
+ )} {tab === 'teams' && !!user?.tier?.team_members && isGeneral && (
diff --git a/apps/frontend/src/components/marketplace/special.message.tsx b/apps/frontend/src/components/marketplace/special.message.tsx index 22bcab07..8ac5fccc 100644 --- a/apps/frontend/src/components/marketplace/special.message.tsx +++ b/apps/frontend/src/components/marketplace/special.message.tsx @@ -15,6 +15,7 @@ import dynamic from 'next/dynamic'; import { IntegrationContext } from '@gitroom/frontend/components/launches/helpers/use.integration'; import dayjs from 'dayjs'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; +import { newDayjs } from '@gitroom/frontend/components/layout/set.timezone'; const PreviewPopupDynamic = dynamic(() => import('@gitroom/frontend/components/marketplace/preview.popup.dynamic').then( (mod) => mod.PreviewPopupDynamic @@ -279,7 +280,7 @@ export const Post: FC<{ { - return dayjs(message.createdAt).format('h:mm A'); + return newDayjs(message.createdAt).format('h:mm A'); }, [message]); return (
diff --git a/apps/frontend/src/components/new-launch/add.edit.modal.tsx b/apps/frontend/src/components/new-launch/add.edit.modal.tsx index 8498ff4f..1c01faae 100644 --- a/apps/frontend/src/components/new-launch/add.edit.modal.tsx +++ b/apps/frontend/src/components/new-launch/add.edit.modal.tsx @@ -8,6 +8,7 @@ import { ManageModal } from '@gitroom/frontend/components/new-launch/manage.moda import { Integrations } from '@gitroom/frontend/components/launches/calendar.context'; import { useShallow } from 'zustand/react/shallow'; import { useExistingData } from '@gitroom/frontend/components/launches/helpers/use.existing.data'; +import { newDayjs } from '@gitroom/frontend/components/layout/set.timezone'; export interface AddEditModalProps { dummy?: boolean; @@ -46,7 +47,7 @@ export const AddEditModal: FC = (props) => { const integrations = useLaunchStore((state) => state.integrations); useEffect(() => { setDummy(!!props.dummy); - setDate(props.date || dayjs()); + setDate(props.date || newDayjs()); setAllIntegrations(props.allIntegrations || []); setIsCreateSet(!!props.addEditSets); }, []); diff --git a/apps/frontend/src/components/new-launch/store.ts b/apps/frontend/src/components/new-launch/store.ts index 6f0ecac2..6d2c2c45 100644 --- a/apps/frontend/src/components/new-launch/store.ts +++ b/apps/frontend/src/components/new-launch/store.ts @@ -6,6 +6,7 @@ import { Integrations } from '@gitroom/frontend/components/launches/calendar.con import { createRef, RefObject } from 'react'; import { arrayMoveImmutable } from 'array-move'; import { PostComment } from '@gitroom/frontend/components/new-launch/providers/high.order.provider'; +import { newDayjs } from '@gitroom/frontend/components/layout/set.timezone'; interface Values { id: string; @@ -129,7 +130,7 @@ const initialState = { loaded: true, dummy: false, activateExitButton: true, - date: dayjs(), + date: newDayjs(), postComment: PostComment.ALL, tags: [] as { label: string; value: string }[], totalChars: 0, diff --git a/apps/frontend/src/components/post-url-selector/post.url.selector.tsx b/apps/frontend/src/components/post-url-selector/post.url.selector.tsx index 88cfefbb..c2c793f2 100644 --- a/apps/frontend/src/components/post-url-selector/post.url.selector.tsx +++ b/apps/frontend/src/components/post-url-selector/post.url.selector.tsx @@ -9,6 +9,7 @@ import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; import removeMd from 'remove-markdown'; import clsx from 'clsx'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; +import { newDayjs } from '@gitroom/frontend/components/layout/set.timezone'; const postUrlEmitter = new EventEmitter(); export const ShowPostSelector = () => { const [showPostSelector, setShowPostSelector] = useState(false); @@ -19,7 +20,7 @@ export const ShowPostSelector = () => { return tag; }, } as any); - const [date, setDate] = useState(dayjs()); + const [date, setDate] = useState(newDayjs()); useEffect(() => { postUrlEmitter.on( 'show', @@ -35,14 +36,14 @@ export const ShowPostSelector = () => { return () => { setShowPostSelector(false); setCallback(null); - setDate(dayjs()); + setDate(newDayjs()); postUrlEmitter.removeAllListeners(); }; }, []); const close = useCallback(() => { setShowPostSelector(false); setCallback(null); - setDate(dayjs()); + setDate(newDayjs()); }, []); if (!showPostSelector) { return <>; diff --git a/apps/frontend/src/components/sets/sets.tsx b/apps/frontend/src/components/sets/sets.tsx index c0b440e2..ab01add9 100644 --- a/apps/frontend/src/components/sets/sets.tsx +++ b/apps/frontend/src/components/sets/sets.tsx @@ -14,6 +14,7 @@ import { deleteDialog } from '@gitroom/react/helpers/delete.dialog'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; import dayjs from 'dayjs'; import { AddEditModal } from '@gitroom/frontend/components/new-launch/add.edit.modal'; +import { newDayjs } from '@gitroom/frontend/components/layout/set.timezone'; const SaveSetModal: FC<{ postData: any; @@ -142,7 +143,7 @@ export const Sets: FC = () => { reopenModal={() => {}} mutate={() => {}} integrations={integrations} - date={dayjs()} + date={newDayjs()} /> ), size: '80%', diff --git a/apps/frontend/src/components/settings/global.settings.tsx b/apps/frontend/src/components/settings/global.settings.tsx new file mode 100644 index 00000000..449e38f8 --- /dev/null +++ b/apps/frontend/src/components/settings/global.settings.tsx @@ -0,0 +1,21 @@ +'use client'; + +import React from 'react'; +import { useT } from '@gitroom/react/translation/get.transation.service.client'; +import dynamic from 'next/dynamic'; + +const MetricComponent = dynamic( + () => import('@gitroom/frontend/components/settings/metric.component'), + { + ssr: false, + } +); +export const GlobalSettings = () => { + const t = useT(); + return ( +
+

{t('global_settings', 'Global Settings')}

+ +
+ ); +}; diff --git a/apps/frontend/src/components/settings/metric.component.tsx b/apps/frontend/src/components/settings/metric.component.tsx new file mode 100644 index 00000000..d91ae891 --- /dev/null +++ b/apps/frontend/src/components/settings/metric.component.tsx @@ -0,0 +1,70 @@ +'use client'; + +import { Select } from '@gitroom/react/form/select'; +import React, { useState } from 'react'; +import { isUSCitizen } from '@gitroom/frontend/components/launches/helpers/isuscitizen.utils'; +import timezones from 'timezones-list'; +const dateMetrics = [ + { label: 'AM:PM', value: 'US' }, + { label: '24 hours', value: 'GLOBAL' }, +]; + +import dayjs from 'dayjs'; +import timezone from 'dayjs/plugin/timezone'; +dayjs.extend(timezone); + +const MetricComponent = () => { + const [currentMetric, setCurrentMetric] = useState(isUSCitizen()); + const [timezone, setTimezone] = useState( + localStorage.getItem('timezone') || dayjs.tz.guess() + ); + const changeMetric = (event: React.ChangeEvent) => { + const value = event.target.value; + setCurrentMetric(value === 'US'); + localStorage.setItem('isUS', value); + }; + + const changeTimezone = (event: React.ChangeEvent) => { + const value = event.target.value; + console.log(value); + setTimezone(value); + localStorage.setItem('timezone', value); + dayjs.tz.setDefault(value); + }; + return ( +
+
Date Metrics
+ + +
Current Timezone
+ +
+ ); +}; + +export default MetricComponent; diff --git a/apps/frontend/src/components/settings/settings.component.tsx b/apps/frontend/src/components/settings/settings.component.tsx deleted file mode 100644 index 41312008..00000000 --- a/apps/frontend/src/components/settings/settings.component.tsx +++ /dev/null @@ -1,80 +0,0 @@ -'use client'; - -import { GithubComponent } from '@gitroom/frontend/components/settings/github.component'; -import { useCallback, useEffect } from 'react'; -import { useUser } from '@gitroom/frontend/components/layout/user.context'; -import { TeamsComponent } from '@gitroom/frontend/components/settings/teams.component'; -import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; -import useSWR from 'swr'; -import { LoadingComponent } from '@gitroom/frontend/components/layout/loading'; -import { useRouter } from 'next/navigation'; -import { useVariables } from '@gitroom/react/helpers/variable.context'; -import { useT } from '@gitroom/react/translation/get.transation.service.client'; -export const SettingsComponent = () => { - const { isGeneral } = useVariables(); - const user = useUser(); - const router = useRouter(); - const fetch = useFetch(); - const load = useCallback(async (path: string) => { - const { github } = await (await fetch('/settings/github')).json(); - if (!github) { - return false; - } - const emptyOnes = github.find((p: { login: string }) => !p.login); - const { organizations } = emptyOnes - ? await (await fetch(`/settings/organizations/${emptyOnes.id}`)).json() - : { - organizations: [], - }; - return { - github, - organizations, - }; - }, []); - const { isLoading: isLoadingSettings, data: loadAll } = useSWR( - 'load-all', - load - ); - useEffect(() => { - if (!isLoadingSettings && !loadAll) { - router.push('/'); - } - }, [loadAll, isLoadingSettings]); - - const t = useT(); - - if (isLoadingSettings) { - return ; - } - if (!loadAll) { - return null; - } - return ( -
- {!isGeneral && ( -
-

- {t('your_git_repository', 'Your Git Repository')} -

-
- {t( - 'connect_your_github_repository_to_receive_updates_and_analytics', - 'Connect your GitHub repository to receive updates and analytics' - )} -
- - {/*
*/} - {/*
*/} - {/* */} - {/*
*/} - {/*
Show news with everybody in Gitroom
*/} - {/*
*/} -
- )} - {!!user?.tier?.team_members && } -
- ); -}; diff --git a/apps/frontend/src/components/standalone-modal/standalone.modal.tsx b/apps/frontend/src/components/standalone-modal/standalone.modal.tsx index 35a49da6..fe160dc2 100644 --- a/apps/frontend/src/components/standalone-modal/standalone.modal.tsx +++ b/apps/frontend/src/components/standalone-modal/standalone.modal.tsx @@ -7,6 +7,7 @@ import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; import dayjs from 'dayjs'; import { useParams } from 'next/navigation'; import { AddEditModal } from '@gitroom/frontend/components/new-launch/add.edit.modal'; +import { newDayjs } from '@gitroom/frontend/components/layout/set.timezone'; export const StandaloneModal: FC = () => { const fetch = useFetch(); const params = useParams<{ platform: string }>(); @@ -17,7 +18,7 @@ export const StandaloneModal: FC = () => { const loadDate = useCallback(async () => { if (params.platform === 'all') { - return dayjs().utc().format('YYYY-MM-DDTHH:mm:ss'); + return newDayjs().utc().format('YYYY-MM-DDTHH:mm:ss'); } return (await (await fetch('/posts/find-slot')).json()).date; }, []); diff --git a/libraries/react-shared-libraries/src/translation/locales/en/translation.json b/libraries/react-shared-libraries/src/translation/locales/en/translation.json index c3f7d0a9..da85902b 100644 --- a/libraries/react-shared-libraries/src/translation/locales/en/translation.json +++ b/libraries/react-shared-libraries/src/translation/locales/en/translation.json @@ -13,6 +13,7 @@ "video_made_with_ai": "Video made with AI", "please_add_at_least": "Please add at least 20 chars", "send_invitation_via_email": "Send invitation via email?", + "global_settings": "Global Settings", "copy_id": "Copy Channel ID", "team_members": "Team Members", "invite_your_assistant_or_team_member_to_manage_your_account": "Invite your assistant or team member to manage your account", diff --git a/package.json b/package.json index ee298420..5bed657f 100644 --- a/package.json +++ b/package.json @@ -212,6 +212,7 @@ "tailwind-scrollbar": "^3.1.0", "tailwindcss": "3.4.17", "tailwindcss-rtl": "^0.9.0", + "timezones-list": "^3.1.0", "tippy.js": "^6.3.7", "tldts": "^6.1.47", "transloadit": "^3.0.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 03a22762..35bd4f27 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -516,6 +516,9 @@ importers: tailwindcss-rtl: specifier: ^0.9.0 version: 0.9.0 + timezones-list: + specifier: ^3.1.0 + version: 3.1.0 tippy.js: specifier: ^6.3.7 version: 6.3.7 @@ -14263,6 +14266,9 @@ packages: thunky@1.1.0: resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} + timezones-list@3.1.0: + resolution: {integrity: sha512-PcDBt9tae330KTOIufK/wArTlJp+unuuRcG0EEu+4oLHZACHefKQyP2D51gMZID+urye92mHND60KRVuDDAmbA==} + tiny-case@1.0.3: resolution: {integrity: sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==} @@ -33423,6 +33429,8 @@ snapshots: thunky@1.1.0: optional: true + timezones-list@3.1.0: {} + tiny-case@1.0.3: {} tiny-inflate@1.0.3: {}