diff --git a/apps/back-office/.storybook/preview-head.html b/apps/back-office/.storybook/preview-head.html
deleted file mode 100644
index 6f789ce0d..000000000
--- a/apps/back-office/.storybook/preview-head.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
diff --git a/apps/back-office/.storybook/preview.tsx b/apps/back-office/.storybook/preview.tsx
index 9913e8f12..0b1734f9b 100644
--- a/apps/back-office/.storybook/preview.tsx
+++ b/apps/back-office/.storybook/preview.tsx
@@ -31,9 +31,6 @@ export const globalTypes = {
},
};
-document.body.style.fontFamily =
- '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"';
-
const preview: Preview = {
parameters: {
...parameters,
diff --git a/apps/back-office/styles/globals.css b/apps/back-office/styles/globals.css
index 596256fcc..2e9afb0c1 100644
--- a/apps/back-office/styles/globals.css
+++ b/apps/back-office/styles/globals.css
@@ -4,6 +4,11 @@
@layer base {
:root {
+ --default-font-stack: -apple-system, system-ui, BlinkMacSystemFont,
+ 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif,
+ 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
+ 'Noto Color Emoji';
+
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
@@ -236,7 +241,7 @@
}
body {
- @apply h-full font-sans antialiased;
+ font-family: var(--font-sans, var(--default-font-stack));
}
body,
diff --git a/apps/unlock/.storybook/preview-head.html b/apps/unlock/.storybook/preview-head.html
deleted file mode 100644
index 6f789ce0d..000000000
--- a/apps/unlock/.storybook/preview-head.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
diff --git a/apps/unlock/.storybook/preview.tsx b/apps/unlock/.storybook/preview.tsx
index 8eee57373..8db2248b6 100644
--- a/apps/unlock/.storybook/preview.tsx
+++ b/apps/unlock/.storybook/preview.tsx
@@ -30,8 +30,6 @@ export const globalTypes = {
},
};
-document.body.classList.add('font-sans');
-
const preview: Preview = {
parameters: {
...parameters,
diff --git a/apps/web/.storybook/preview-head.html b/apps/web/.storybook/preview-head.html
deleted file mode 100644
index 6f789ce0d..000000000
--- a/apps/web/.storybook/preview-head.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
diff --git a/apps/web/.storybook/preview.tsx b/apps/web/.storybook/preview.tsx
index 6fc908aac..fe18d2724 100644
--- a/apps/web/.storybook/preview.tsx
+++ b/apps/web/.storybook/preview.tsx
@@ -29,10 +29,6 @@ export const globalTypes = {
},
},
};
-
-document.body.style.fontFamily =
- '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"';
-
const preview: Preview = {
parameters: {
...parameters,
diff --git a/apps/web/styles/globals.css b/apps/web/styles/globals.css
index fc3d48954..64a7fd5e6 100644
--- a/apps/web/styles/globals.css
+++ b/apps/web/styles/globals.css
@@ -4,6 +4,11 @@
@layer base {
:root {
+ --default-font-stack: -apple-system, system-ui, BlinkMacSystemFont,
+ 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif,
+ 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
+ 'Noto Color Emoji';
+
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
@@ -197,7 +202,7 @@
}
body {
- @apply h-full font-sans antialiased;
+ font-family: var(--font-sans, var(--default-font-stack));
}
body,
diff --git a/libs/gql/admin/api/src/queries/organizer/event/eventParameters.spec.ts b/libs/gql/admin/api/src/queries/organizer/event/eventParameters.spec.ts
index f2b0dd3f5..9405bb5de 100644
--- a/libs/gql/admin/api/src/queries/organizer/event/eventParameters.spec.ts
+++ b/libs/gql/admin/api/src/queries/organizer/event/eventParameters.spec.ts
@@ -7,6 +7,9 @@ import {
} from '@test-utils/db';
import { adminSdk } from '../../../generated';
+import { addHoursInTimeZone, subHoursInTimeZone } from '@time';
+import { toZonedTime } from 'date-fns-tz';
+
describe('eventParameters integration tests', () => {
process.env.TZ = 'Europe/London';
let client: PgClient;
@@ -27,6 +30,9 @@ describe('eventParameters integration tests', () => {
jest.resetAllMocks();
});
+ const timeZone = 'Europe/London';
+ const currentDate = new Date();
+
it('should not access eventParameters not PUBLISHED', async () => {
const res = await adminSdk.GetEventParameters({
eventId: 'clocula4d04g40bw1t9zefsuc',
@@ -35,15 +41,14 @@ describe('eventParameters integration tests', () => {
});
describe('eventParameters for event with timezone Europe/London, same as the one in test', () => {
it('should return isOngoing true if event is ongoing', async () => {
- const currentDate = new Date();
await updateObjects(
client,
'eventParameters',
{
- dateStart: new Date(currentDate.getTime() - 1000 * 60 * 60), // 1 hour before
- dateEnd: new Date(currentDate.getTime() + 1000 * 60 * 60), // 1 hour after
- dateSaleStart: new Date(currentDate.getTime() - 2000 * 60 * 60), // 2 hours before
- dateSaleEnd: new Date(currentDate.getTime() + 2000 * 60 * 60), // 2 hours after
+ dateStart: subHoursInTimeZone(currentDate, 2, timeZone),
+ dateEnd: addHoursInTimeZone(currentDate, 2, timeZone),
+ dateSaleStart: subHoursInTimeZone(currentDate, 2, timeZone),
+ dateSaleEnd: addHoursInTimeZone(currentDate, 2, timeZone),
},
{ eventId: 'clizzpvidao620buvxit1ynko' },
);
@@ -55,15 +60,14 @@ describe('eventParameters integration tests', () => {
});
it('should return isOngoing false if event is not ongoing', async () => {
- const currentDate = new Date();
await updateObjects(
client,
'eventParameters',
{
- dateStart: new Date(currentDate.getTime() + 1000 * 60 * 60), // 1 hour after
- dateEnd: new Date(currentDate.getTime() + 2000 * 60 * 60), // 2 hours after
- dateSaleStart: new Date(currentDate.getTime() - 2000 * 60 * 60), // 2 hours before
- dateSaleEnd: new Date(currentDate.getTime() - 1000 * 60 * 60), // 1 hour before
+ dateStart: subHoursInTimeZone(currentDate, 6, timeZone), // 6 hours before
+ dateEnd: subHoursInTimeZone(currentDate, 1, timeZone), // 1 hour before
+ dateSaleStart: subHoursInTimeZone(currentDate, 2, timeZone), // 2 hours before
+ dateSaleEnd: subHoursInTimeZone(currentDate, 1, timeZone), // 1 hour before
},
{ eventId: 'clizzpvidao620buvxit1ynko' },
);
@@ -75,15 +79,14 @@ describe('eventParameters integration tests', () => {
});
it('should return isSaleOngoing true if sale is ongoing', async () => {
- const currentDate = new Date();
await updateObjects(
client,
'eventParameters',
{
- dateStart: new Date(currentDate.getTime() - 2000 * 60 * 60), // 2 hours before
- dateEnd: new Date(currentDate.getTime() + 2000 * 60 * 60), // 2 hours after
- dateSaleStart: new Date(currentDate.getTime() - 1000 * 60 * 60), // 1 hour before
- dateSaleEnd: new Date(currentDate.getTime() + 1000 * 60 * 60), // 1 hour after
+ dateStart: subHoursInTimeZone(currentDate, 2, timeZone), // 2 hours before
+ dateEnd: addHoursInTimeZone(currentDate, 2, timeZone), // 2 hours after
+ dateSaleStart: subHoursInTimeZone(currentDate, 1, timeZone), // 1 hour before
+ dateSaleEnd: addHoursInTimeZone(currentDate, 1, timeZone), // 1 hour after
},
{ eventId: 'clizzpvidao620buvxit1ynko' },
);
@@ -95,15 +98,14 @@ describe('eventParameters integration tests', () => {
});
it('should return isSaleOngoing false if sale is not ongoing', async () => {
- const currentDate = new Date();
await updateObjects(
client,
'eventParameters',
{
- dateStart: new Date(currentDate.getTime() - 2000 * 60 * 60), // 2 hours before
- dateEnd: new Date(currentDate.getTime() + 2000 * 60 * 60), // 2 hours after
- dateSaleStart: new Date(currentDate.getTime() + 1000 * 60 * 60), // 1 hour after
- dateSaleEnd: new Date(currentDate.getTime() + 2000 * 60 * 60), // 2 hours after
+ dateStart: subHoursInTimeZone(currentDate, 2, timeZone), // 2 hours before
+ dateEnd: addHoursInTimeZone(currentDate, 2, timeZone), // 2 hours after
+ dateSaleStart: subHoursInTimeZone(currentDate, 4, timeZone), // 4 hours before
+ dateSaleEnd: subHoursInTimeZone(currentDate, 1, timeZone), // 1 hour before
},
{ eventId: 'clizzpvidao620buvxit1ynko' },
);
@@ -119,7 +121,7 @@ describe('eventParameters integration tests', () => {
// Adjust for the timezone difference between New York and London
const timezoneOffset = 1000 * 60 * 60 * 5; // 5 hours
it('should return isOngoing true if event is ongoing', async () => {
- const currentDate = new Date();
+ const currentDate = toZonedTime(new Date(), 'Europe/London');
await updateObjects(
client,
'eventParameters',
@@ -147,7 +149,7 @@ describe('eventParameters integration tests', () => {
});
it('should return isOngoing false if event is not ongoing', async () => {
- const currentDate = new Date();
+ const currentDate = toZonedTime(new Date(), 'Europe/London');
await updateObjects(
client,
'eventParameters',
@@ -175,7 +177,7 @@ describe('eventParameters integration tests', () => {
});
it('should return isSaleOngoing true if sale is ongoing', async () => {
- const currentDate = new Date();
+ const currentDate = toZonedTime(new Date(), 'Europe/London');
await updateObjects(
client,
'eventParameters',
@@ -203,7 +205,7 @@ describe('eventParameters integration tests', () => {
});
it('should return isSaleOngoing false if sale is not ongoing', async () => {
- const currentDate = new Date();
+ const currentDate = toZonedTime(new Date(), 'Europe/London');
await updateObjects(
client,
'eventParameters',
diff --git a/libs/time/src/index.ts b/libs/time/src/index.ts
index 7431343e5..8cdc9042e 100644
--- a/libs/time/src/index.ts
+++ b/libs/time/src/index.ts
@@ -2,3 +2,4 @@ export * from './lib/UTCDate';
export * from './lib/UTCDateMini';
export * from './lib/getSteppedIntervalTime';
export * from './lib/useNow';
+export * from './lib/utils';
diff --git a/libs/time/src/lib/utils.ts b/libs/time/src/lib/utils.ts
new file mode 100644
index 000000000..07c1fbbcf
--- /dev/null
+++ b/libs/time/src/lib/utils.ts
@@ -0,0 +1,47 @@
+import { addHours, subHours } from 'date-fns';
+import { format, toZonedTime } from 'date-fns-tz';
+
+/**
+ * Converts a date to a specified time zone and formats it for display or further processing.
+ * @param {Date} date - The date to convert.
+ * @param {string} timeZone - The IANA time zone name.
+ * @returns {string} - The formatted date string in the specified time zone.
+ */
+export const convertDateToTimeZone = (date: Date, timeZone: string): string => {
+ const zonedDate = toZonedTime(date, timeZone);
+ return format(zonedDate, 'yyyy-MM-dd HH:mm:ssXXX', { timeZone });
+};
+
+/**
+ * Adds hours to a date in a specific time zone.
+ * @param {Date} date - The original date.
+ * @param {number} hours - The number of hours to add.
+ * @param {string} timeZone - The IANA time zone name.
+ * @returns {Date} - The new date with added hours, considered in the specified time zone.
+ */
+export const addHoursInTimeZone = (
+ date: Date,
+ hours: number,
+ timeZone: string,
+): Date => {
+ const zonedDate = toZonedTime(date, timeZone);
+ const newDate = addHours(zonedDate, hours);
+ return toZonedTime(newDate, timeZone); // Convert back if needed, or adjust as per use case
+};
+
+/**
+ * Subtracts hours from a date in a specific time zone.
+ * @param {Date} date - The original date.
+ * @param {number} hours - The number of hours to subtract.
+ * @param {string} timeZone - The IANA time zone name.
+ * @returns {Date} - The new date with subtracted hours, considered in the specified time zone.
+ */
+export const subHoursInTimeZone = (
+ date: Date,
+ hours: number,
+ timeZone: string,
+): Date => {
+ const zonedDate = toZonedTime(date, timeZone);
+ const newDate = subHours(zonedDate, hours);
+ return toZonedTime(newDate, timeZone); // Convert back if needed, or adjust as per use case
+};
diff --git a/libs/ui/components/.storybook/globals.css b/libs/ui/components/.storybook/globals.css
index ad37dc451..4d39dd218 100644
--- a/libs/ui/components/.storybook/globals.css
+++ b/libs/ui/components/.storybook/globals.css
@@ -4,6 +4,11 @@
@layer base {
:root {
+ --default-font-stack: -apple-system, system-ui, BlinkMacSystemFont,
+ 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif,
+ 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
+ 'Noto Color Emoji';
+
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
@@ -236,8 +241,8 @@
}
body {
- font-family: 'Inter', sans-serif;
- @apply h-full font-sans antialiased;
+ font-family: var(--font-sans, var(--default-font-stack));
+ @apply h-full antialiased;
}
.pt-square {
diff --git a/libs/ui/components/.storybook/preview-head.html b/libs/ui/components/.storybook/preview-head.html
deleted file mode 100644
index 11b17fd16..000000000
--- a/libs/ui/components/.storybook/preview-head.html
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
diff --git a/libs/ui/components/.storybook/preview.tsx b/libs/ui/components/.storybook/preview.tsx
index 55303e0d0..30b1d114f 100644
--- a/libs/ui/components/.storybook/preview.tsx
+++ b/libs/ui/components/.storybook/preview.tsx
@@ -20,9 +20,6 @@ export const DarkModeDecorator: Decorator = (Story: any, context: any = {}) => {
return dark ? : ;
};
-document.body.style.fontFamily =
- '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"';
-
const preview: Preview = {
parameters: {
...parameters,