Eve/src/components/DateTimeSettings.ts
Danny Morabito dc9abee715
🎨 🚀 Overhaul UI/UX with comprehensive design system improvements
 Features added:

- 🔍 Implement functional search in header navigation
- ⚙️ Add basic user settings page
- 📱 Make dashboard fully responsive

🔧 Enhancements:

- 🎭 Standardize CSS with consistent theming across components
- 🧹 Remove unused CSS for better performance
- 📊 Improve dashboard layout and visual hierarchy
- 📦 Redesign last block widget for better usability

💅 This commit introduces a cohesive design system with functional design-token components for a more  polished user experience.
2025-03-20 09:46:47 +01:00

296 lines
8.3 KiB
TypeScript

import { StyledToggle } from '@/components/General/Toggle';
import { LitElement, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import '@components/General/Input';
import '@components/General/Fieldset';
import '@components/General/Select';
interface DateTimeFormatOptions {
locale: string;
weekday: 'long' | 'short' | 'narrow' | '';
year: 'numeric' | '2-digit' | '';
month: 'numeric' | '2-digit' | 'long' | 'short' | 'narrow' | '';
day: 'numeric' | '2-digit' | '';
hour: 'numeric' | '2-digit' | '';
minute: 'numeric' | '2-digit' | '';
second: 'numeric' | '2-digit' | '';
hour12: boolean;
}
const DEFAULT_OPTIONS: DateTimeFormatOptions = {
locale: 'en-US',
weekday: 'short',
year: 'numeric',
month: 'long',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: true,
};
@customElement('arx-date-time-settings')
export class DateTimeSettings extends LitElement {
@state()
private options: DateTimeFormatOptions = { ...DEFAULT_OPTIONS };
@state()
private previewDate = new Date();
override connectedCallback() {
super.connectedCallback();
this.loadFromLocalStorage();
setInterval(() => {
this.previewDate = new Date();
this.requestUpdate();
}, 1000);
}
private loadFromLocalStorage() {
const savedOptions = localStorage.getItem('dateTimeFormatOptions');
if (savedOptions) {
try {
this.options = { ...DEFAULT_OPTIONS, ...JSON.parse(savedOptions) };
} catch (e) {
console.error('Failed to parse saved options', e);
this.options = { ...DEFAULT_OPTIONS };
}
}
}
private saveToLocalStorage() {
localStorage.setItem('dateTimeFormatOptions', JSON.stringify(this.options));
this.dispatchEvent(
new CustomEvent('settings-changed', {
bubbles: true,
composed: true,
detail: { options: this.options },
}),
);
}
private handleChange(key: keyof DateTimeFormatOptions, e: Event) {
const target = e.target as HTMLSelectElement | HTMLInputElement | StyledToggle;
let value: string | boolean | undefined = target.value;
if (key === 'hour12' && target instanceof StyledToggle) value = target.checked;
this.options = {
...this.options,
[key]: value,
};
if (key === 'locale') this.requestUpdate();
this.saveToLocalStorage();
}
private formatWithOption(option: string, type: keyof DateTimeFormatOptions): string {
if (option === '') return '';
const date = this.previewDate;
const locale = this.options.locale;
const formatterOptions: Intl.DateTimeFormatOptions = {
[type]: option,
};
// Special case for hour to respect hour12 setting
if (type === 'hour') formatterOptions.hour12 = this.options.hour12;
try {
return new Intl.DateTimeFormat(locale, formatterOptions).format(date);
} catch (e) {
console.error(`Error formatting with option ${option} for ${type}`, e);
return 'Error: Invalid format';
}
}
private formatPreview(): string {
return new Date(this.previewDate).toLocaleString(this.options.locale, {
weekday: this.options.weekday === '' ? undefined : this.options.weekday,
year: this.options.year === '' ? undefined : this.options.year,
month: this.options.month === '' ? undefined : this.options.month,
day: this.options.day === '' ? undefined : this.options.day,
hour: this.options.hour === '' ? undefined : this.options.hour,
minute: this.options.minute === '' ? undefined : this.options.minute,
second: this.options.second === '' ? undefined : this.options.second,
hour12: this.options.hour12,
});
}
override render() {
return html`
<arx-fieldset legend="Date/Time Settings">
<arx-input
label="Locale"
type="text"
.value=${this.options.locale}
@input=${(e: Event) => this.handleChange('locale', e)}
>
</arx-input>
<arx-select
label="Weekday Format"
.value=${this.options.weekday}
@change=${(e: Event) => this.handleChange('weekday', e)}
.options=${[
{
value: 'long',
label: `Long (${this.formatWithOption('long', 'weekday')})`,
},
{
value: 'short',
label: `Short (${this.formatWithOption('short', 'weekday')})`,
},
{
value: 'narrow',
label: `Narrow (${this.formatWithOption('narrow', 'weekday')})`,
},
]}
></arx-select>
<arx-select
label="Year Format"
.value=${this.options.year}
@change=${(e: Event) => this.handleChange('year', e)}
.options=${[
{
value: 'numeric',
label: `Numeric (${this.formatWithOption('numeric', 'year')})`,
},
{
value: '2-digit',
label: `2-digit (${this.formatWithOption('2-digit', 'year')})`,
},
{
value: '',
label: 'None',
},
]}
></arx-select>
<arx-select
label="Month Format"
.value=${this.options.month}
@change=${(e: Event) => this.handleChange('month', e)}
.options=${[
{
value: 'long',
label: `Long (${this.formatWithOption('long', 'month')})`,
},
{
value: 'short',
label: `Short (${this.formatWithOption('short', 'month')})`,
},
{
value: 'narrow',
label: `Narrow (${this.formatWithOption('narrow', 'month')})`,
},
{
value: 'numeric',
label: `Numeric (${this.formatWithOption('numeric', 'month')})`,
},
{
value: '2-digit',
label: `2-digit (${this.formatWithOption('2-digit', 'month')})`,
},
{
value: '',
label: 'None',
},
]}
></arx-select>
<arx-select
label="Day Format"
.value=${this.options.day}
@change=${(e: Event) => this.handleChange('day', e)}
.options=${[
{
value: 'numeric',
label: `Numeric (${this.formatWithOption('numeric', 'day')})`,
},
{
value: '2-digit',
label: `2-digit (${this.formatWithOption('2-digit', 'day')})`,
},
{
value: '',
label: 'None',
},
]}
></arx-select>
<arx-select
label="Hour Format"
.value=${this.options.hour}
@change=${(e: Event) => this.handleChange('hour', e)}
.options=${[
{
value: 'numeric',
label: 'Numeric',
},
{
value: '2-digit',
label: '2-digit',
},
{
value: '',
label: 'None',
},
]}
></arx-select>
<arx-select
label="Minute Format"
.value=${this.options.minute}
@change=${(e: Event) => this.handleChange('minute', e)}
.options=${[
{
value: 'numeric',
label: 'Numeric',
},
{
value: '2-digit',
label: '2-digit',
},
{
value: '',
label: 'None',
},
]}
></arx-select>
<arx-select
label="Second Format"
.value=${this.options.second}
@change=${(e: Event) => this.handleChange('second', e)}
.options=${[
{
value: 'numeric',
label: 'Numeric',
},
{
value: '2-digit',
label: '2-digit',
},
{
value: '',
label: 'None',
},
]}
></arx-select>
<arx-toggle
label="Use 12-hour format"
?checked=${this.options.hour12}
@change=${(e: Event) => this.handleChange('hour12', e)}
></arx-toggle>
<h3>Preview</h3>
<p>${this.formatPreview()}</p>
</arx-fieldset>
`;
}
}