mirror of
https://github.com/polaroi8d/cactoide.git
synced 2026-03-22 22:25:29 +00:00
Compare commits
9 Commits
feat/suppo
...
fix/date-t
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
accfd540f0 | ||
|
|
9b1ef64618 | ||
|
|
c340088434 | ||
|
|
984c296725 | ||
|
|
9acfa08ea8 | ||
|
|
45cb95f6a8 | ||
|
|
8426bd5704 | ||
|
|
b9833db3bb | ||
|
|
b3572293ba |
92
package-lock.json
generated
92
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "event-cactus",
|
||||
"version": "0.0.1",
|
||||
"version": "0.1.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "event-cactus",
|
||||
"version": "0.0.1",
|
||||
"version": "0.1.1",
|
||||
"dependencies": {
|
||||
"@sveltejs/adapter-node": "^5.3.1",
|
||||
"drizzle-orm": "^0.44.5",
|
||||
@@ -35,7 +35,7 @@
|
||||
"tailwindcss": "^4.0.0",
|
||||
"typescript": "^5.0.0",
|
||||
"typescript-eslint": "^8.20.0",
|
||||
"vite": "^7.0.4"
|
||||
"vite": "^7.1.10"
|
||||
}
|
||||
},
|
||||
"node_modules/@drizzle-team/brocli": {
|
||||
@@ -1949,6 +1949,66 @@
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": {
|
||||
"version": "1.4.5",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@emnapi/wasi-threads": "1.0.4",
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": {
|
||||
"version": "1.4.5",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
|
||||
"version": "1.0.4",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": {
|
||||
"version": "0.2.12",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@emnapi/core": "^1.4.3",
|
||||
"@emnapi/runtime": "^1.4.3",
|
||||
"@tybys/wasm-util": "^0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": {
|
||||
"version": "0.10.0",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": {
|
||||
"version": "2.8.0",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "0BSD",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
||||
"version": "4.1.12",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.12.tgz",
|
||||
@@ -2602,9 +2662,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/devalue": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/devalue/-/devalue-5.1.1.tgz",
|
||||
"integrity": "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==",
|
||||
"version": "5.4.1",
|
||||
"resolved": "https://registry.npmjs.org/devalue/-/devalue-5.4.1.tgz",
|
||||
"integrity": "sha512-YtoaOfsqjbZQKGIMRYDWKjUmSB4VJ/RElB+bXZawQAQYAo4xu08GKTMVlsZDTF6R2MbAgjcAQRPI5eIyRAT2OQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/drizzle-kit": {
|
||||
@@ -4737,13 +4797,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tinyglobby": {
|
||||
"version": "0.2.14",
|
||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz",
|
||||
"integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==",
|
||||
"version": "0.2.15",
|
||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
||||
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fdir": "^6.4.4",
|
||||
"picomatch": "^4.0.2"
|
||||
"fdir": "^6.5.0",
|
||||
"picomatch": "^4.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
@@ -4864,17 +4924,17 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-7.1.2.tgz",
|
||||
"integrity": "sha512-J0SQBPlQiEXAF7tajiH+rUooJPo0l8KQgyg4/aMunNtrOa7bwuZJsJbDWzeljqQpgftxuq5yNJxQ91O9ts29UQ==",
|
||||
"version": "7.1.10",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-7.1.10.tgz",
|
||||
"integrity": "sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"fdir": "^6.4.6",
|
||||
"fdir": "^6.5.0",
|
||||
"picomatch": "^4.0.3",
|
||||
"postcss": "^8.5.6",
|
||||
"rollup": "^4.43.0",
|
||||
"tinyglobby": "^0.2.14"
|
||||
"tinyglobby": "^0.2.15"
|
||||
},
|
||||
"bin": {
|
||||
"vite": "bin/vite.js"
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
"tailwindcss": "^4.0.0",
|
||||
"typescript": "^5.0.0",
|
||||
"typescript-eslint": "^8.20.0",
|
||||
"vite": "^7.0.4"
|
||||
"vite": "^7.1.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sveltejs/adapter-node": "^5.3.1",
|
||||
|
||||
22
src/hooks.server.ts
Normal file
22
src/hooks.server.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
// src/hooks.server.ts
|
||||
import type { Handle } from '@sveltejs/kit';
|
||||
import { generateUserId } from '$lib/generateUserId.js';
|
||||
|
||||
export const handle: Handle = async ({ event, resolve }) => {
|
||||
const cactoideUserId = event.cookies.get('cactoideUserId');
|
||||
const userId = generateUserId();
|
||||
|
||||
const DAYS = 400; // practical upper bound in many browsers for cookies
|
||||
const MAX_AGE = 60 * 60 * 24 * DAYS;
|
||||
const PATH = '/';
|
||||
|
||||
if (!cactoideUserId) {
|
||||
console.debug(`There is no cactoideUserId cookie, generating new one...`);
|
||||
event.cookies.set('cactoideUserId', userId, { path: PATH, maxAge: MAX_AGE });
|
||||
} else {
|
||||
console.debug(`cactoideUserId: ${cactoideUserId}`);
|
||||
console.debug(`cactoideUserId cookie found, using existing one...`);
|
||||
}
|
||||
|
||||
return resolve(event);
|
||||
};
|
||||
@@ -15,7 +15,10 @@ export interface CalendarEvent {
|
||||
* Formats a date and time string for iCal format (UTC)
|
||||
*/
|
||||
export const formatDateForICal = (date: string, time: string): string => {
|
||||
const eventDate = new Date(`${date}T${time}`);
|
||||
// Parse date and time as local timezone to avoid timezone issues
|
||||
const [year, month, day] = date.split('-').map(Number);
|
||||
const [hours, minutes, seconds] = time.split(':').map(Number);
|
||||
const eventDate = new Date(year, month - 1, day, hours, minutes, seconds || 0);
|
||||
return eventDate.toISOString().replace(/[-:]/g, '').split('.')[0] + 'Z';
|
||||
};
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import type { Event } from './types';
|
||||
|
||||
export const formatDate = (dateString: string): string => {
|
||||
const date = new Date(dateString);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
return `${year}/${month}/${day}`;
|
||||
// Parse the date string as local date to avoid timezone issues
|
||||
// Split the date string and create a Date object in local timezone
|
||||
const [year, month, day] = dateString.split('-').map(Number);
|
||||
const date = new Date(year, month - 1, day); // month is 0-indexed in Date constructor
|
||||
const formattedYear = date.getFullYear();
|
||||
const formattedMonth = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const formattedDay = String(date.getDate()).padStart(2, '0');
|
||||
return `${formattedYear}/${formattedMonth}/${formattedDay}`;
|
||||
};
|
||||
|
||||
export const formatTime = (timeString: string): string => {
|
||||
@@ -17,7 +20,10 @@ export const formatTime = (timeString: string): string => {
|
||||
export const isEventInTimeRange = (event: Event, timeFilter: string): boolean => {
|
||||
if (timeFilter === 'any') return true;
|
||||
|
||||
const eventDate = new Date(`${event.date}T${event.time}`);
|
||||
// Parse date and time as local timezone to avoid timezone issues
|
||||
const [year, month, day] = event.date.split('-').map(Number);
|
||||
const [hours, minutes, seconds] = event.time.split(':').map(Number);
|
||||
const eventDate = new Date(year, month - 1, day, hours, minutes, seconds || 0);
|
||||
const now = new Date();
|
||||
|
||||
// Handle temporal status filters
|
||||
|
||||
@@ -1,20 +1,5 @@
|
||||
import { generateUserId } from '$lib/generateUserId.js';
|
||||
|
||||
export function load({ cookies }) {
|
||||
const cactoideUserId = cookies.get('cactoideUserId');
|
||||
const userId = generateUserId();
|
||||
|
||||
const DAYS = 400; // practical upper bound in many browsers for cookies
|
||||
const MAX_AGE = 60 * 60 * 24 * DAYS;
|
||||
const PATH = '/';
|
||||
|
||||
if (!cactoideUserId) {
|
||||
console.debug(`There is no cactoideUserId cookie, generating new one...`);
|
||||
cookies.set('cactoideUserId', userId, { path: PATH, maxAge: MAX_AGE });
|
||||
} else {
|
||||
console.debug(`cactoideUserId: ${cactoideUserId}`);
|
||||
console.debug(`cactoideUserId cookie found, using existing one...`);
|
||||
}
|
||||
|
||||
return {
|
||||
cactoideUserId
|
||||
|
||||
@@ -56,7 +56,13 @@ export const actions: Actions = {
|
||||
});
|
||||
}
|
||||
|
||||
if (new Date(date) < new Date()) {
|
||||
// Check if date is in the past using local timezone
|
||||
const [year, month, day] = date.split('-').map(Number);
|
||||
const eventDate = new Date(year, month - 1, day);
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
|
||||
if (eventDate < today) {
|
||||
return fail(400, {
|
||||
error: 'Date cannot be in the past.',
|
||||
values: {
|
||||
@@ -105,7 +111,7 @@ export const actions: Actions = {
|
||||
type: type,
|
||||
attendeeLimit: type === 'limited' ? parseInt(attendeeLimit) : null,
|
||||
visibility: visibility,
|
||||
userId: userId
|
||||
userId: userId!
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Unexpected error', error);
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
<script lang="ts">
|
||||
import type { Event, EventType } from '$lib/types';
|
||||
import { goto } from '$app/navigation';
|
||||
import type { PageData } from '../$types';
|
||||
import { formatTime, formatDate, isEventInTimeRange } from '$lib/dateHelpers';
|
||||
import { t } from '$lib/i18n/i18n.js';
|
||||
import Fuse from 'fuse.js';
|
||||
|
||||
type DiscoverPageData = {
|
||||
events: Event[];
|
||||
};
|
||||
|
||||
let publicEvents: Event[] = [];
|
||||
let error = '';
|
||||
let searchQuery = '';
|
||||
@@ -16,7 +19,7 @@
|
||||
let showFilters = false;
|
||||
let fuse: Fuse<Event>;
|
||||
|
||||
export let data: PageData;
|
||||
export let data: DiscoverPageData;
|
||||
// Use the server-side data
|
||||
$: publicEvents = data?.events || [];
|
||||
|
||||
@@ -67,8 +70,15 @@
|
||||
|
||||
// Sort events by date and time
|
||||
events = events.sort((a, b) => {
|
||||
const dateA = new Date(`${a.date}T${a.time}`);
|
||||
const dateB = new Date(`${b.date}T${b.time}`);
|
||||
// Parse dates as local timezone to avoid timezone issues
|
||||
const parseEventDateTime = (event: Event) => {
|
||||
const [year, month, day] = event.date.split('-').map(Number);
|
||||
const [hours, minutes, seconds] = event.time.split(':').map(Number);
|
||||
return new Date(year, month - 1, day, hours, minutes, seconds || 0);
|
||||
};
|
||||
|
||||
const dateA = parseEventDateTime(a);
|
||||
const dateB = parseEventDateTime(b);
|
||||
|
||||
if (selectedSortOrder === 'asc') {
|
||||
return dateA.getTime() - dateB.getTime();
|
||||
|
||||
@@ -86,8 +86,9 @@ export const actions: Actions = {
|
||||
});
|
||||
}
|
||||
|
||||
// Check if date is in the past (but allow editing past events for corrections)
|
||||
const eventDate = new Date(date);
|
||||
// Check if date is in the past using local timezone (but allow editing past events for corrections)
|
||||
const [year, month, day] = date.split('-').map(Number);
|
||||
const eventDate = new Date(year, month - 1, day);
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user