fix(dashboard): handle complex date/weather formats in Scene Info

Fixed display issues with user's actual data formats:

Date Field Fix:
- Changed from simple "day + month" to using parsed fields
- Now displays data.month ("3rd Day of the Ninth Month")
- With data.weekday ("Tuesday") as label
- Handles complex comma-separated date strings correctly
- No more "JAN Friday, January..." overflow

Weather Field Fix:
- Added validation to check if weatherEmoji is actual emoji
- Expanded emoji detection regex to cover more Unicode ranges
- Falls back to ☀️ if weatherEmoji is text (like "Clear")
- Prevents "Clear 🌙 Clear skies" duplication
- Now shows just "Clear skies 🌙"

Location Field Fix:
- Changed split pattern from /[,\-]/ to comma-only
- Preserves hyphens in names (e.g., "Seol Yi-hwan")
- No more splitting "Seol Yi-hwan's Private Quarters"
- Secondary location parts (after comma) shown as label

Technical Changes:
- formatDate() now takes (fullDate, weekday, month) params
- Uses month field as primary display value
- formatWeather() validates emoji with expanded regex
- formatLocation() splits on comma only, preserves hyphens
- All formatters handle complex user-defined formats

Addresses parseInfoBoxData's comma-split parsing:
"Tuesday, 3rd Day of Ninth Month, Autumn, Year..." becomes:
  weekday: "Tuesday"
  month: "3rd Day of Ninth Month" (displayed)
  year: "Autumn" (not shown - save space)
This commit is contained in:
Lucas 'Paperboy' Rose-Winters
2025-11-03 15:35:29 +11:00
parent 637ee15666
commit 381b656bde
@@ -13,25 +13,30 @@ import { parseInfoBoxData } from './infoBoxWidgets.js';
/**
* Format date for display
* @param {string} date - Date value
* @param {string} month - Month name
* @param {string} fullDate - Full date string from infoBox
* @param {string} weekday - Weekday name
* @param {string} month - Month/day description (e.g. "3rd Day of the Ninth Month")
* @returns {Object} Formatted date parts
*/
function formatDate(date, month, weekday) {
if (!date && !month && !weekday) {
function formatDate(fullDate, weekday, month) {
if (!fullDate && !month) {
return { icon: '📅', value: 'No Date', label: '' };
}
// Format: "15 Jan" on main line, "Monday" as label
const monthShort = month ? month.substring(0, 3) : 'Mon';
const dayNum = date || '1';
const weekdayLabel = weekday || '';
// parseInfoBoxData splits date on commas:
// "Tuesday, 3rd Day of the Ninth Month, Autumn, Year..." becomes:
// weekday = "Tuesday"
// month = "3rd Day of the Ninth Month"
// year = "Autumn"
// Display the most important part (month/day) with weekday as label
const displayValue = month || fullDate;
const displayLabel = weekday || '';
return {
icon: '📅',
value: `${dayNum} ${monthShort}`,
label: weekdayLabel
value: displayValue,
label: displayLabel
};
}
@@ -53,14 +58,24 @@ function formatTime(timeStart, timeEnd) {
/**
* Format weather for display
* @param {string} weatherEmoji - Weather emoji
* @param {string} weatherEmoji - Weather emoji or emoji string
* @param {string} weatherForecast - Weather description
* @returns {Object} Formatted weather parts
*/
function formatWeather(weatherEmoji, weatherForecast) {
const emoji = weatherEmoji || '☀️';
// Data format is "Weather: emoji, forecast" parsed as:
// weatherEmoji = emoji character(s)
// weatherForecast = description text
// Display just the forecast with emoji at the end
const forecast = weatherForecast || 'Clear';
// Only add emoji if it's actually an emoji (not text like "Clear")
// Check if weatherEmoji looks like an emoji (short string with emoji characters)
const emojiRegex = /[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/u;
const isEmoji = weatherEmoji && weatherEmoji.length <= 3 && emojiRegex.test(weatherEmoji);
const emoji = isEmoji ? weatherEmoji : '☀️';
return {
icon: '', // No icon on left
value: `${forecast} ${emoji}`, // Forecast text with emoji on right
@@ -95,11 +110,13 @@ function formatLocation(location) {
return { value: 'No Location', label: '' };
}
// Split on comma or dash for secondary text
const parts = location.split(/[,\-]/);
// Split on comma only (not hyphen - those are part of names)
// Example: "Seol Yi-hwan's Private Quarters, Palace District"
// -> value: "Seol Yi-hwan's Private Quarters", label: "Palace District"
const parts = location.split(',').map(p => p.trim());
return {
value: parts[0].trim(),
label: parts.slice(1).join(', ').trim()
value: parts[0],
label: parts.slice(1).join(', ')
};
}
@@ -258,7 +275,7 @@ export function registerSceneInfoWidget(registry, dependencies) {
const data = parseInfoBoxData(getInfoBoxData());
// Format data for display
const date = formatDate(data.date, data.month, data.weekday);
const date = formatDate(data.date, data.weekday, data.month);
const time = formatTime(data.timeStart, data.timeEnd);
const weather = formatWeather(data.weatherEmoji, data.weatherForecast);
const temp = formatTemp(data.temperature);