import { css, html, LitElement, nothing } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { PLANET_GLYPH } from '../tokens/index.js'; import type { GetChoghadiyaResponse } from '../types/index.js'; import { baseStyles } from '../utils/base-styles.js'; import { capitalize } from '../utils/string.js'; type ChoghadiyaPeriod = GetChoghadiyaResponse['dayChoghadiya'][number]; /** * Format an ISO 8601 datetime string to a short local time (HH:MM). * Falls back to the raw string when parsing fails. */ function fmtTime(iso: string): string { try { const d = new Date(iso); if (Number.isNaN(d.getTime())) return iso; return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); } catch { return iso; } } /** * Choghadiya muhurta grid. Accepts a GetChoghadiyaResponse and renders * 8 daytime and 8 nighttime muhurta tiles in a two-column responsive layout. * Good periods are highlighted in green, Bad periods in red. */ @customElement('roxy-choghadiya-grid') export class RoxyChoghadiyaGrid extends LitElement { static styles = [ baseStyles, css` .wrap { display: grid; gap: var(--roxy-space-md, 1rem); } .header { display: grid; gap: var(--roxy-space-xs, 0.25rem); } .title { font-size: var(--roxy-text-lg, 1.125rem); font-weight: var(--roxy-weight-bold, 600); margin: 0; } .subtitle { font-size: var(--roxy-text-sm, 0.875rem); color: var(--roxy-muted, #71717a); margin: 0; } .cho-grid { display: grid; grid-template-columns: 1fr; gap: var(--roxy-space-md, 1rem); } @media (min-width: 720px) { .cho-grid { grid-template-columns: 1fr 1fr; } } .period-col { display: grid; gap: var(--roxy-space-xs, 0.25rem); } .period-heading { font-size: var(--roxy-text-base, 1rem); font-weight: var(--roxy-weight-bold, 600); margin: 0 0 var(--roxy-space-xs, 0.25rem); color: var(--roxy-fg, #0a0a0a); } .cho-tile { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 0.25em 0.75em; padding: 0.55em 0.85em; border: 1px solid var(--roxy-border, #e4e4e7); border-radius: var(--roxy-radius-md, 8px); } .cho-tile.good { background: color-mix(in srgb, var(--roxy-success, #22c55e) 18%, transparent); border-color: color-mix(in srgb, var(--roxy-success, #22c55e) 45%, transparent); color: var(--roxy-fg, #0a0a0a); } .cho-tile.bad { background: color-mix(in srgb, var(--roxy-danger, #ef4444) 18%, transparent); border-color: color-mix(in srgb, var(--roxy-danger, #ef4444) 45%, transparent); color: var(--roxy-fg, #0a0a0a); } .cho-tile.neutral { background: transparent; color: var(--roxy-fg, #0a0a0a); } .tile-name { font-size: var(--roxy-text-base, 1rem); font-weight: var(--roxy-weight-bold, 600); grid-column: 1; } .tile-time { font-size: var(--roxy-text-xs, 0.75rem); opacity: 0.8; white-space: nowrap; grid-column: 2; grid-row: 1 / 3; text-align: right; align-self: center; } .tile-lord { font-size: var(--roxy-text-sm, 0.875rem); opacity: 0.85; grid-column: 1; display: flex; align-items: center; gap: 0.25em; } `, ]; @property({ attribute: false }) data: GetChoghadiyaResponse | null = null; private renderTile(period: ChoghadiyaPeriod) { const effectClass = period.effect === 'Good' ? 'good' : period.effect === 'Bad' ? 'bad' : 'neutral'; const lordGlyph = PLANET_GLYPH[capitalize(period.lord)] ?? ''; const timeRange = `${fmtTime(period.start)} - ${fmtTime(period.end)}`; return html`
${period.name} ${timeRange} ${lordGlyph ? html`` : nothing} ${period.lord}
`; } render() { if (!this.data) return html`
No choghadiya data
`; const { date, dayChoghadiya, nightChoghadiya } = this.data; return html`

Choghadiya

${date ? html`

${date}

` : nothing}

Day

${ dayChoghadiya && dayChoghadiya.length > 0 ? dayChoghadiya.map((p) => this.renderTile(p)) : html`

No daytime periods

` }

Night

${ nightChoghadiya && nightChoghadiya.length > 0 ? nightChoghadiya.map((p) => this.renderTile(p)) : html`

No nighttime periods

` }
`; } } declare global { interface HTMLElementTagNameMap { 'roxy-choghadiya-grid': RoxyChoghadiyaGrid; } }