@treely/strapi-slices 7.5.5 → 7.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ import { FormatNumberOptions } from 'react-intl';
2
+ declare const convertStrapiTime: (date: string, formatNumber: (value: number | bigint, opts?: FormatNumberOptions) => string) => string;
3
+ export default convertStrapiTime;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@treely/strapi-slices",
3
- "version": "7.5.5",
3
+ "version": "7.6.0",
4
4
  "license": "MIT",
5
5
  "author": "Tree.ly FlexCo",
6
6
  "description": "@treely/strapi-slices is a open source library maintained by Tree.ly.",
@@ -153,7 +153,8 @@
153
153
  "formik": "^2.4.5",
154
154
  "framer-motion": "^10.16.5",
155
155
  "mapbox-gl": "^2.15.0",
156
- "swr": "^2.3.2"
156
+ "swr": "^2.3.2",
157
+ "yocto-queue": "^1.2.0"
157
158
  },
158
159
  "msw": {
159
160
  "workerDirectory": [
@@ -46,9 +46,13 @@ describe('The EventCard component', () => {
46
46
  it('displays start and end date and time correctly', () => {
47
47
  setup();
48
48
 
49
- expect(
50
- screen.getByText(/3\/12\/2024\s*\|\s*08:30\s*-\s*09:30/i)
51
- ).toBeInTheDocument();
49
+ const textContent = screen.getByText(
50
+ /02\/12\/2024\s*\|\s*08:30\s*-\s*03\/12\/2024\s*\|\s*09:30/i
51
+ ).textContent;
52
+
53
+ const normalizedText = textContent?.replace(/\s+/g, ' ').trim();
54
+
55
+ expect(normalizedText).toBe('02/12/2024 | 08:30 - 03/12/2024 | 09:30');
52
56
  });
53
57
 
54
58
  it('displays the speakers', async () => {
@@ -36,6 +36,7 @@ import { BREAKPOINT_MD_QUERY } from '../../constants/breakpoints';
36
36
  import StrapiEvent, { EventType } from '../../models/strapi/StrapiEvent';
37
37
  import { IntlContext } from '../ContextProvider';
38
38
  import strapiMediaUrl from '../../utils/strapiMediaUrl';
39
+ import convertStrapiTime from '../../utils/convertStrapiTime';
39
40
 
40
41
  export interface EventCardProps {
41
42
  event: StrapiEvent;
@@ -208,27 +209,22 @@ export const EventCard = ({ event }: EventCardProps): JSX.Element => {
208
209
  color={'var(--boemly-colors-primary-700)'}
209
210
  />
210
211
  <Text size={['xsLowBold', null, null, 'smLowBold']}>
211
- {formatDate(event.start, {
212
+ {formatDate(event.startDate, {
212
213
  year: 'numeric',
213
214
  month: '2-digit',
214
215
  day: '2-digit',
215
- })}{' '}
216
- |{' '}
217
- {formatNumber(new Date(event.start).getUTCHours(), {
218
- minimumIntegerDigits: 2,
219
- })}
220
- :
221
- {formatNumber(new Date(event.start).getUTCMinutes(), {
222
- minimumIntegerDigits: 2,
223
- })}{' '}
224
- -{' '}
225
- {formatNumber(new Date(event.end).getUTCHours(), {
226
- minimumIntegerDigits: 2,
227
- })}
228
- :
229
- {formatNumber(new Date(event.end).getUTCMinutes(), {
230
- minimumIntegerDigits: 2,
231
216
  })}
217
+ {event.startTime &&
218
+ ` | ${convertStrapiTime(event.startTime, formatNumber)} `}
219
+ {(event.endDate || event.endTime) && ' - '}
220
+ {event.endDate &&
221
+ formatDate(event.endDate, {
222
+ year: 'numeric',
223
+ month: '2-digit',
224
+ day: '2-digit',
225
+ })}
226
+ {event.endTime && event.endDate && ' | '}
227
+ {event.endTime && convertStrapiTime(event.endTime, formatNumber)}
232
228
  </Text>
233
229
  </Flex>
234
230
  </Flex>
@@ -41,8 +41,10 @@ interface StrapiEvent {
41
41
  location?: string;
42
42
  locale: Locale;
43
43
  online?: boolean;
44
- start: Date;
45
- end: Date;
44
+ startDate: Date;
45
+ startTime?: string;
46
+ endDate?: Date;
47
+ endTime?: string;
46
48
  slices: any[];
47
49
  localizations: StrapiLocalization[];
48
50
  topBanner?: StrapiTopBanner;
@@ -19,7 +19,7 @@ const pastEventMock = {
19
19
  attributes: {
20
20
  ...strapiEventMock.attributes,
21
21
  title: 'Past Event',
22
- start: '2024-12-01T10:00:00.000Z',
22
+ startDate: '2024-12-01',
23
23
  eventTypes: [{ id: 1, eventType: EventType.MEET_UP }],
24
24
  languages: [{ id: 1, language: 'English', countryCode: 'GB' }],
25
25
  },
@@ -30,7 +30,7 @@ const upcomingEventMock = {
30
30
  attributes: {
31
31
  ...strapiEventMock.attributes,
32
32
  title: 'Upcoming Event',
33
- start: '2025-02-01T10:00:00.000Z',
33
+ startDate: '2025-02-01',
34
34
  eventTypes: [{ id: 1, eventType: EventType.CONFERENCE }],
35
35
  languages: [{ id: 1, language: 'German', countryCode: 'DE' }],
36
36
  },
@@ -68,7 +68,7 @@ describe('The Events slice', () => {
68
68
  const key = getKey(0, null);
69
69
  getKeyCalls.push(key.toString());
70
70
 
71
- if (getKey.toString().includes('filters[start][$gte]')) {
71
+ if (getKey.toString().includes('filters[startDate][$gte]')) {
72
72
  return {
73
73
  data: [{ body: { data: [upcomingEventMock] } }],
74
74
  isLoading: false,
@@ -77,7 +77,7 @@ describe('The Events slice', () => {
77
77
  loadMore: jest.fn(),
78
78
  };
79
79
  }
80
- if (getKey.toString().includes('filters[start][$lt]')) {
80
+ if (getKey.toString().includes('filters[startDate][$lt]')) {
81
81
  return {
82
82
  data: [{ body: { data: [pastEventMock] } }],
83
83
  isLoading: false,
@@ -149,7 +149,7 @@ describe('The Events slice', () => {
149
149
  // Use past events for the testing, because the batch for past events is defined as 2 and
150
150
  // the "Load button" will be shown when there are more then 2 past events
151
151
  (useEvents as jest.Mock).mockImplementation(({ getKey }) => {
152
- if (getKey.toString().includes('filters[start][$lt]')) {
152
+ if (getKey.toString().includes('filters[startDate][$lt]')) {
153
153
  return {
154
154
  data: [
155
155
  {
@@ -243,7 +243,7 @@ describe('The Events slice', () => {
243
243
  await waitFor(() => {
244
244
  expect(getKeyCalls.map(decodeURIComponent)).toEqual(
245
245
  expect.arrayContaining([
246
- expect.stringContaining('filters[start][$gte]'),
246
+ expect.stringContaining('filters[startDate][$gte]'),
247
247
  expect.stringContaining(
248
248
  'filters[$or][0][eventTypes][eventType]=Conference'
249
249
  ),
@@ -278,7 +278,7 @@ describe('The Events slice', () => {
278
278
  await waitFor(() => {
279
279
  expect(getKeyCalls.map(decodeURIComponent)).toEqual(
280
280
  expect.arrayContaining([
281
- expect.stringContaining('filters[start][$gte]'),
281
+ expect.stringContaining('filters[startDate][$gte]'),
282
282
  expect.stringContaining(
283
283
  'filters[$or][0][languages][language]=German'
284
284
  ),
@@ -303,7 +303,7 @@ describe('The Events slice', () => {
303
303
  expect(getKeyCalls.map(decodeURIComponent)).toEqual(
304
304
  expect.arrayContaining([
305
305
  expect.stringContaining(
306
- `filters[start][$gte]=${NOW.toISOString()}`
306
+ `filters[startDate][$gte]=${NOW.toISOString()}`
307
307
  ),
308
308
  ])
309
309
  );
@@ -341,7 +341,9 @@ describe('The Events slice', () => {
341
341
  await waitFor(() => {
342
342
  expect(getKeyCalls.map(decodeURIComponent)).toEqual(
343
343
  expect.arrayContaining([
344
- expect.stringContaining(`filters[start][$lt]=${NOW.toISOString()}`),
344
+ expect.stringContaining(
345
+ `filters[startDate][$lt]=${NOW.toISOString()}`
346
+ ),
345
347
  ])
346
348
  );
347
349
  });
@@ -87,7 +87,7 @@ export const Events: React.FC<EventsProps> = ({ slice }: EventsProps) => {
87
87
  ) => {
88
88
  const url = new URL(`/treely-events`, STRAPI_URI);
89
89
  url.searchParams.append(
90
- 'pagination[start]',
90
+ 'pagination[startDate]',
91
91
  (index * batchSize).toString()
92
92
  );
93
93
  url.searchParams.append('pagination[limit]', batchSize.toString());
@@ -96,9 +96,9 @@ export const Events: React.FC<EventsProps> = ({ slice }: EventsProps) => {
96
96
  url.searchParams.append('pLevel', STRAPI_DEFAULT_POPULATE_DEPTH);
97
97
 
98
98
  if (sort[0] === Sort.OLDEST_FIRST) {
99
- url.searchParams.append('sort', 'start:asc');
99
+ url.searchParams.append('sort', 'startDate:asc');
100
100
  } else {
101
- url.searchParams.append('sort', 'start:desc');
101
+ url.searchParams.append('sort', 'startDate:desc');
102
102
  }
103
103
 
104
104
  if (eventTypeFilter.length) {
@@ -123,12 +123,13 @@ export const Events: React.FC<EventsProps> = ({ slice }: EventsProps) => {
123
123
 
124
124
  const getUpcomingKey: SWRInfiniteKeyLoader = useCallback(
125
125
  (index) =>
126
- buildEventsUrl(index, UPCOMING_BATCH_SIZE, 'filters[start][$gte]'),
126
+ buildEventsUrl(index, UPCOMING_BATCH_SIZE, 'filters[startDate][$gte]'),
127
127
  [eventTypeFilter, languageFilter, sort]
128
128
  );
129
129
 
130
130
  const getPastKey: SWRInfiniteKeyLoader = useCallback(
131
- (index) => buildEventsUrl(index, PAST_BATCH_SIZE, 'filters[start][$lt]'),
131
+ (index) =>
132
+ buildEventsUrl(index, PAST_BATCH_SIZE, 'filters[startDate][$lt]'),
132
133
  [eventTypeFilter, languageFilter, sort]
133
134
  );
134
135
 
@@ -14,8 +14,10 @@ export const strapiEventMock: IStrapiData<StrapiEvent> = {
14
14
  logo: { id: 1, alt: 'Logo alt text 1', img: { data: strapiMediaMock } },
15
15
  eventTypes: [{ id: 1, eventType: EventType.MEET_UP }],
16
16
  languages: [{ id: 1, language: 'English', countryCode: 'GB' }],
17
- start: new Date('2024-03-12T08:30:00Z'),
18
- end: new Date('2024-03-12T09:30:00Z'),
17
+ startDate: new Date('2024-02-12'),
18
+ startTime: '08:30:00.000',
19
+ endDate: new Date('2024-03-12'),
20
+ endTime: '09:30:00.000',
19
21
  title: 'Event Title',
20
22
  description: 'Event Description',
21
23
  button: { id: 1, text: 'Button text', url: 'https://tree.ly' },
@@ -0,0 +1,21 @@
1
+ import convertStrapiTime from './convertStrapiTime';
2
+
3
+ describe('The convertStrapiTime util', () => {
4
+ it('returns the correct time', () => {
5
+ const formatNumber = jest.fn((number) =>
6
+ number.toString().padStart(2, '0')
7
+ );
8
+ const time = '12:45:00.000';
9
+
10
+ expect(convertStrapiTime(time, formatNumber)).toBe('12:45');
11
+ });
12
+
13
+ it('returns the correct amount of digits', () => {
14
+ const formatNumber = jest.fn((number) =>
15
+ number.toString().padStart(2, '0')
16
+ );
17
+ const time = '08:05:00.000';
18
+
19
+ expect(convertStrapiTime(time, formatNumber)).toBe('08:05');
20
+ });
21
+ });
@@ -0,0 +1,19 @@
1
+ import { FormatNumberOptions } from 'react-intl';
2
+
3
+ const convertStrapiTime = (
4
+ date: string,
5
+ formatNumber: (value: number | bigint, opts?: FormatNumberOptions) => string
6
+ ): string => {
7
+ let tempTime = date.split(':');
8
+ let dt = new Date();
9
+ dt.setHours(parseInt(tempTime[0], 10), parseInt(tempTime[1], 10), 0, 0);
10
+ const time = new Date(dt.getTime() - dt.getTimezoneOffset() * 60000);
11
+
12
+ return `${formatNumber(time.getUTCHours(), {
13
+ minimumIntegerDigits: 2,
14
+ })}:${formatNumber(time.getUTCMinutes(), {
15
+ minimumIntegerDigits: 2,
16
+ })}`;
17
+ };
18
+
19
+ export default convertStrapiTime;