🎨 ✨ 🚀 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.
This commit is contained in:
parent
5afeb4d01a
commit
dc9abee715
49 changed files with 4176 additions and 2468 deletions
296
src/components/DateTimeSettings.ts
Normal file
296
src/components/DateTimeSettings.ts
Normal file
|
@ -0,0 +1,296 @@
|
|||
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>
|
||||
`;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue