feat: Space Booking System - MVP complet
Sistem web pentru rezervarea de birouri și săli de ședință cu flux de aprobare administrativă. Stack: FastAPI + Vue.js 3 + SQLite + TypeScript Features implementate: - Autentificare JWT + Self-registration cu email verification - CRUD Spații, Utilizatori, Settings (Admin) - Calendar interactiv (FullCalendar) cu drag-and-drop - Creare rezervări cu validare (durată, program, overlap, max/zi) - Rezervări recurente (săptămânal) - Admin: aprobare/respingere/anulare cereri - Admin: creare directă rezervări (bypass approval) - Admin: editare orice rezervare - User: editare/anulare rezervări proprii - Notificări in-app (bell icon + dropdown) - Notificări email (async SMTP cu BackgroundTasks) - Jurnal acțiuni administrative (audit log) - Rapoarte avansate (utilizare, top users, approval rate) - Șabloane rezervări (booking templates) - Atașamente fișiere (upload/download) - Conflict warnings (verificare disponibilitate real-time) - Integrare Google Calendar (OAuth2) - Suport timezone (UTC storage + user preference) - 225+ teste backend Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
117
frontend/src/utils/datetime.ts
Normal file
117
frontend/src/utils/datetime.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* Utility functions for timezone-aware datetime formatting.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Format a datetime string in the user's timezone.
|
||||
*
|
||||
* @param datetime - ISO datetime string from API (in UTC)
|
||||
* @param timezone - IANA timezone string (e.g., "Europe/Bucharest")
|
||||
* @param options - Intl.DateTimeFormat options
|
||||
* @returns Formatted datetime string
|
||||
*/
|
||||
export const formatDateTime = (
|
||||
datetime: string,
|
||||
timezone: string = 'UTC',
|
||||
options?: Intl.DateTimeFormatOptions
|
||||
): string => {
|
||||
const date = new Date(datetime)
|
||||
|
||||
const defaultOptions: Intl.DateTimeFormatOptions = {
|
||||
timeZone: timezone,
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
...options
|
||||
}
|
||||
|
||||
return new Intl.DateTimeFormat('ro-RO', defaultOptions).format(date)
|
||||
}
|
||||
|
||||
/**
|
||||
* Format date only (no time) in user's timezone.
|
||||
*/
|
||||
export const formatDate = (datetime: string, timezone: string = 'UTC'): string => {
|
||||
return formatDateTime(datetime, timezone, {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: undefined,
|
||||
minute: undefined
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Format time only in user's timezone.
|
||||
*/
|
||||
export const formatTime = (datetime: string, timezone: string = 'UTC'): string => {
|
||||
const date = new Date(datetime)
|
||||
return new Intl.DateTimeFormat('ro-RO', {
|
||||
timeZone: timezone,
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
}).format(date)
|
||||
}
|
||||
|
||||
/**
|
||||
* Format datetime with timezone abbreviation.
|
||||
*/
|
||||
export const formatDateTimeWithTZ = (datetime: string, timezone: string = 'UTC'): string => {
|
||||
const date = new Date(datetime)
|
||||
|
||||
const formatted = new Intl.DateTimeFormat('ro-RO', {
|
||||
timeZone: timezone,
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
timeZoneName: 'short'
|
||||
}).format(date)
|
||||
|
||||
return formatted
|
||||
}
|
||||
|
||||
/**
|
||||
* Get timezone abbreviation (e.g., "EET", "EEST").
|
||||
*/
|
||||
export const getTimezoneAbbr = (timezone: string = 'UTC'): string => {
|
||||
const date = new Date()
|
||||
const formatted = new Intl.DateTimeFormat('en-US', {
|
||||
timeZone: timezone,
|
||||
timeZoneName: 'short'
|
||||
}).format(date)
|
||||
|
||||
// Extract timezone abbreviation from formatted string
|
||||
const match = formatted.match(/,\s*(.+)/)
|
||||
return match ? match[1] : timezone.split('/').pop() || 'UTC'
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert local datetime-local input to ISO string (for API).
|
||||
* The input from datetime-local is in user's local time, so we just add seconds and Z.
|
||||
*/
|
||||
export const localDateTimeToISO = (localDateTime: string): string => {
|
||||
// datetime-local format: "YYYY-MM-DDTHH:mm"
|
||||
// We need to send it as is to the API (API will handle timezone conversion)
|
||||
return localDateTime + ':00'
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert ISO datetime to datetime-local format for input field.
|
||||
*/
|
||||
export const isoToLocalDateTime = (isoDateTime: string, timezone: string = 'UTC'): string => {
|
||||
const date = new Date(isoDateTime)
|
||||
|
||||
// Get the date components in the user's timezone
|
||||
const year = date.toLocaleString('en-US', { timeZone: timezone, year: 'numeric' })
|
||||
const month = date.toLocaleString('en-US', { timeZone: timezone, month: '2-digit' })
|
||||
const day = date.toLocaleString('en-US', { timeZone: timezone, day: '2-digit' })
|
||||
const hour = date.toLocaleString('en-US', { timeZone: timezone, hour: '2-digit', hour12: false })
|
||||
const minute = date.toLocaleString('en-US', { timeZone: timezone, minute: '2-digit' })
|
||||
|
||||
// Format as YYYY-MM-DDTHH:mm for datetime-local input
|
||||
return `${year}-${month}-${day}T${hour.padStart(2, '0')}:${minute}`
|
||||
}
|
||||
Reference in New Issue
Block a user