Skip to content

Commit 7d609a4

Browse files
feat: add calendar configuration for first day of the week
1 parent d0ce440 commit 7d609a4

5 files changed

Lines changed: 148 additions & 1 deletion

File tree

.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ PUBLIC_OBA_SERVER_URL="https://api.pugetsound.onebusaway.org/"
2020

2121
PUBLIC_OTP_SERVER_URL=""
2222

23+
# 1 TUE, 2 WED, 3 THU, 4 FRI, 5 SAT, 6 SUN, 0 MON
24+
PUBLIC_CALENDAR_FIRST_DAY_OF_WEEK=6
25+
2326
# Analytics
2427
PUBLIC_ANALYTICS_DOMAIN=""
2528
PUBLIC_ANALYTICS_ENABLED=true

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ See `.env.example` for an example of the required keys and values.
2828
- `PUBLIC_ANALYTICS_ENABLED` - boolean: (optional).
2929
- `PUBLIC_ANALYTICS_API_HOST` - string: (optional).
3030

31+
## Calendar Configuration
32+
33+
- `PUBLIC_CALENDAR_FIRST_DAY_OF_WEEK` - number: (optional) Sets the first day of the week for calendar components. Use 0 for Monday, 1 for Tuesday, 2 for Wednesday, 3 for Thursday, 4 for Friday, 5 for Saturday, 6 for Sunday. Defaults to 0 (Monday).
34+
3135
### OBA Server
3236

3337
- `PUBLIC_OBA_SERVER_URL` - string: (required) Your OBA API server's URL.

src/config/calendarConfig.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { env } from '$env/dynamic/public';
2+
3+
/**
4+
* Get the first day of the week for calendar components
5+
* @returns {number} 0 for Monday, 1 for Tuesday, 2 for Wednesday, 3 for Thursday, 4 for Friday, 5 for Saturday, 6 for Sunday
6+
*/
7+
export function getFirstDayOfWeek() {
8+
const configValue = env.PUBLIC_CALENDAR_FIRST_DAY_OF_WEEK;
9+
10+
// Default to Monday (0) if not configured
11+
if (!configValue) {
12+
return 0;
13+
}
14+
15+
const dayValue = parseInt(configValue, 10);
16+
17+
if (
18+
isNaN(dayValue) ||
19+
dayValue < 0 ||
20+
dayValue > 6 ||
21+
dayValue.toString() !== configValue.trim()
22+
) {
23+
console.warn(
24+
'Invalid PUBLIC_CALENDAR_FIRST_DAY_OF_WEEK value. Must be 0-6 (0=Monday, 6=Sunday). Using Monday (0) as default.'
25+
);
26+
return 0;
27+
}
28+
29+
return dayValue;
30+
}

src/routes/stops/[stopID]/schedule/+page.svelte

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import { Datepicker } from 'flowbite-svelte';
1010
import { onMount } from 'svelte';
1111
import { t } from 'svelte-i18n';
12+
import { getFirstDayOfWeek } from '$config/calendarConfig.js';
1213
1314
let selectedDate = $state(new Date());
1415
let prevSelectedDate = $state(null);
@@ -144,7 +145,11 @@
144145
145146
<div class="mb-4 flex gap-4">
146147
<div class="z-20 min-w-32 md:w-[30%]">
147-
<Datepicker bind:value={selectedDate} inputClass="w-96" />
148+
<Datepicker
149+
bind:value={selectedDate}
150+
inputClass="w-96"
151+
firstDayOfWeek={getFirstDayOfWeek()}
152+
/>
148153
</div>
149154
150155
<div class="flex-1 text-right">
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import { describe, it, expect, vi, beforeEach } from 'vitest';
2+
3+
// Mock the environment module
4+
vi.mock('$env/dynamic/public', () => ({
5+
env: {}
6+
}));
7+
8+
import { getFirstDayOfWeek } from '$config/calendarConfig.js';
9+
10+
import { env } from '$env/dynamic/public';
11+
12+
describe('getFirstDayOfWeek', () => {
13+
beforeEach(() => {
14+
vi.clearAllMocks();
15+
16+
Object.keys(env).forEach((key) => delete env[key]);
17+
});
18+
19+
it('returns 0 (Monday) by default when no configuration is set', () => {
20+
expect(getFirstDayOfWeek()).toBe(0);
21+
});
22+
23+
it('returns 0 (Monday) when environment variable is undefined', () => {
24+
env.PUBLIC_CALENDAR_FIRST_DAY_OF_WEEK = undefined;
25+
expect(getFirstDayOfWeek()).toBe(0);
26+
});
27+
28+
it('returns 0 (Monday) when environment variable is empty string', () => {
29+
env.PUBLIC_CALENDAR_FIRST_DAY_OF_WEEK = '';
30+
expect(getFirstDayOfWeek()).toBe(0);
31+
});
32+
33+
it('returns the configured value for all valid day values (0-6)', () => {
34+
// Test all valid values: 0=Monday, 1=Tuesday, 2=Wednesday, 3=Thursday, 4=Friday, 5=Saturday, 6=Sunday
35+
for (let i = 0; i <= 6; i++) {
36+
env.PUBLIC_CALENDAR_FIRST_DAY_OF_WEEK = i.toString();
37+
expect(getFirstDayOfWeek()).toBe(i);
38+
}
39+
});
40+
41+
it('returns 0 (Monday) and shows warning for values above 6', () => {
42+
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
43+
44+
env.PUBLIC_CALENDAR_FIRST_DAY_OF_WEEK = '7';
45+
expect(getFirstDayOfWeek()).toBe(0);
46+
expect(consoleSpy).toHaveBeenCalledWith(
47+
'Invalid PUBLIC_CALENDAR_FIRST_DAY_OF_WEEK value. Must be 0-6 (0=Monday, 6=Sunday). Using Monday (0) as default.'
48+
);
49+
50+
consoleSpy.mockRestore();
51+
});
52+
53+
it('returns 0 (Monday) and shows warning for negative values', () => {
54+
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
55+
56+
env.PUBLIC_CALENDAR_FIRST_DAY_OF_WEEK = '-1';
57+
expect(getFirstDayOfWeek()).toBe(0);
58+
expect(consoleSpy).toHaveBeenCalledWith(
59+
'Invalid PUBLIC_CALENDAR_FIRST_DAY_OF_WEEK value. Must be 0-6 (0=Monday, 6=Sunday). Using Monday (0) as default.'
60+
);
61+
62+
consoleSpy.mockRestore();
63+
});
64+
65+
it('returns 0 (Monday) and shows warning for non-numeric values', () => {
66+
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
67+
68+
// Test various non-numeric strings
69+
const invalidValues = ['invalid', 'monday', 'sunday', 'abc', '1.5', '2.0'];
70+
71+
invalidValues.forEach((value) => {
72+
env.PUBLIC_CALENDAR_FIRST_DAY_OF_WEEK = value;
73+
expect(getFirstDayOfWeek()).toBe(0);
74+
});
75+
76+
expect(consoleSpy).toHaveBeenCalledWith(
77+
'Invalid PUBLIC_CALENDAR_FIRST_DAY_OF_WEEK value. Must be 0-6 (0=Monday, 6=Sunday). Using Monday (0) as default.'
78+
);
79+
80+
consoleSpy.mockRestore();
81+
});
82+
83+
it('handles numeric strings correctly', () => {
84+
// Test that string numbers are parsed correctly
85+
env.PUBLIC_CALENDAR_FIRST_DAY_OF_WEEK = '6';
86+
expect(getFirstDayOfWeek()).toBe(6);
87+
88+
env.PUBLIC_CALENDAR_FIRST_DAY_OF_WEEK = '0';
89+
expect(getFirstDayOfWeek()).toBe(0);
90+
});
91+
92+
it('handles edge case of "0" string vs undefined/empty', () => {
93+
// "0" should be valid and return 0
94+
env.PUBLIC_CALENDAR_FIRST_DAY_OF_WEEK = '0';
95+
expect(getFirstDayOfWeek()).toBe(0);
96+
97+
// undefined should return default 0
98+
env.PUBLIC_CALENDAR_FIRST_DAY_OF_WEEK = undefined;
99+
expect(getFirstDayOfWeek()).toBe(0);
100+
101+
// empty string should return default 0
102+
env.PUBLIC_CALENDAR_FIRST_DAY_OF_WEEK = '';
103+
expect(getFirstDayOfWeek()).toBe(0);
104+
});
105+
});

0 commit comments

Comments
 (0)