refraction almost completed
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
const { getTarotCardDisplayName, getTarotCardSearchAliases } = window.TarotCardImages || {};
|
||||
const calendarDatesUi = window.TarotCalendarDates || {};
|
||||
const calendarDetailUi = window.TarotCalendarDetail || {};
|
||||
const calendarDataUi = window.CalendarDataUi || {};
|
||||
const {
|
||||
addDays,
|
||||
buildSignDateBounds,
|
||||
@@ -29,6 +30,17 @@
|
||||
resolveHolidayGregorianDate
|
||||
} = calendarDatesUi;
|
||||
|
||||
if (
|
||||
typeof calendarDataUi.getMonthDayLinkRows !== "function"
|
||||
|| typeof calendarDataUi.buildDecanTarotRowsForMonth !== "function"
|
||||
|| typeof calendarDataUi.eventSearchText !== "function"
|
||||
|| typeof calendarDataUi.holidaySearchText !== "function"
|
||||
|| typeof calendarDataUi.buildHolidayList !== "function"
|
||||
|| typeof calendarDataUi.buildMonthSearchText !== "function"
|
||||
) {
|
||||
throw new Error("CalendarDataUi module must load before ui-calendar.js");
|
||||
}
|
||||
|
||||
const state = {
|
||||
initialized: false,
|
||||
referenceData: null,
|
||||
@@ -317,116 +329,6 @@
|
||||
};
|
||||
}
|
||||
|
||||
function buildDecanWindow(sign, decanIndex) {
|
||||
const bounds = buildSignDateBounds(sign);
|
||||
const index = Number(decanIndex);
|
||||
if (!bounds || !Number.isFinite(index)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const start = addDays(bounds.start, (index - 1) * 10);
|
||||
const nominalEnd = addDays(start, 9);
|
||||
const end = nominalEnd.getTime() > bounds.end.getTime() ? bounds.end : nominalEnd;
|
||||
|
||||
return {
|
||||
start,
|
||||
end,
|
||||
label: `${formatDateLabel(start)}–${formatDateLabel(end)}`
|
||||
};
|
||||
}
|
||||
|
||||
function listMonthNumbersBetween(start, end) {
|
||||
const result = [];
|
||||
const seen = new Set();
|
||||
const cursor = new Date(start.getFullYear(), start.getMonth(), 1);
|
||||
const limit = new Date(end.getFullYear(), end.getMonth(), 1);
|
||||
|
||||
while (cursor.getTime() <= limit.getTime()) {
|
||||
const monthNo = cursor.getMonth() + 1;
|
||||
if (!seen.has(monthNo)) {
|
||||
seen.add(monthNo);
|
||||
result.push(monthNo);
|
||||
}
|
||||
cursor.setMonth(cursor.getMonth() + 1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function buildDecanTarotRowsForMonth(month) {
|
||||
const monthOrder = Number(month?.order);
|
||||
if (!Number.isFinite(monthOrder)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const rows = [];
|
||||
const seen = new Set();
|
||||
const decansBySign = state.referenceData?.decansBySign || {};
|
||||
|
||||
Object.entries(decansBySign).forEach(([signId, decans]) => {
|
||||
const sign = state.signsById.get(signId);
|
||||
if (!sign || !Array.isArray(decans)) {
|
||||
return;
|
||||
}
|
||||
|
||||
decans.forEach((decan) => {
|
||||
const window = buildDecanWindow(sign, decan?.index);
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
const monthsTouched = listMonthNumbersBetween(window.start, window.end);
|
||||
if (!monthsTouched.includes(monthOrder)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cardName = normalizeMinorTarotCardName(decan?.tarotMinorArcana);
|
||||
if (!cardName) {
|
||||
return;
|
||||
}
|
||||
|
||||
const key = `${cardName}|${signId}|${decan.index}`;
|
||||
if (seen.has(key)) {
|
||||
return;
|
||||
}
|
||||
seen.add(key);
|
||||
|
||||
const startDegree = (Number(decan.index) - 1) * 10;
|
||||
const endDegree = startDegree + 10;
|
||||
const signName = sign?.name?.en || sign?.name || signId;
|
||||
|
||||
rows.push({
|
||||
cardName,
|
||||
signId,
|
||||
signName,
|
||||
signSymbol: sign?.symbol || "",
|
||||
decanIndex: Number(decan.index),
|
||||
startDegree,
|
||||
endDegree,
|
||||
startTime: window.start.getTime(),
|
||||
endTime: window.end.getTime(),
|
||||
startMonth: window.start.getMonth() + 1,
|
||||
startDay: window.start.getDate(),
|
||||
endMonth: window.end.getMonth() + 1,
|
||||
endDay: window.end.getDate(),
|
||||
dateRange: window.label
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
rows.sort((left, right) => {
|
||||
if (left.startTime !== right.startTime) {
|
||||
return left.startTime - right.startTime;
|
||||
}
|
||||
if (left.decanIndex !== right.decanIndex) {
|
||||
return left.decanIndex - right.decanIndex;
|
||||
}
|
||||
return left.cardName.localeCompare(right.cardName);
|
||||
});
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
function buildPlanetMap(planetsObj) {
|
||||
const map = new Map();
|
||||
if (!planetsObj || typeof planetsObj !== "object") {
|
||||
@@ -525,46 +427,6 @@
|
||||
return parseMonthRange(month);
|
||||
}
|
||||
|
||||
function getMonthDayLinkRows(month) {
|
||||
const cacheKey = `${state.selectedCalendar}|${state.selectedYear}|${month?.id || ""}`;
|
||||
if (state.dayLinksCache.has(cacheKey)) {
|
||||
return state.dayLinksCache.get(cacheKey);
|
||||
}
|
||||
|
||||
let dayCount = null;
|
||||
if (state.selectedCalendar === "gregorian") {
|
||||
dayCount = getDaysInMonth(state.selectedYear, Number(month?.order));
|
||||
} else if (state.selectedCalendar === "hebrew" || state.selectedCalendar === "islamic") {
|
||||
const baseDays = Number(month?.days);
|
||||
const variantDays = Number(month?.daysVariant);
|
||||
if (Number.isFinite(baseDays) && Number.isFinite(variantDays)) {
|
||||
dayCount = Math.max(Math.trunc(baseDays), Math.trunc(variantDays));
|
||||
} else if (Number.isFinite(baseDays)) {
|
||||
dayCount = Math.trunc(baseDays);
|
||||
} else if (Number.isFinite(variantDays)) {
|
||||
dayCount = Math.trunc(variantDays);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Number.isFinite(dayCount) || dayCount <= 0) {
|
||||
state.dayLinksCache.set(cacheKey, []);
|
||||
return [];
|
||||
}
|
||||
|
||||
const rows = [];
|
||||
for (let day = 1; day <= dayCount; day += 1) {
|
||||
const gregorianDate = resolveCalendarDayToGregorian(month, day);
|
||||
rows.push({
|
||||
day,
|
||||
gregorianDate: formatIsoDate(gregorianDate),
|
||||
isResolved: Boolean(gregorianDate && !Number.isNaN(gregorianDate.getTime()))
|
||||
});
|
||||
}
|
||||
|
||||
state.dayLinksCache.set(cacheKey, rows);
|
||||
return rows;
|
||||
}
|
||||
|
||||
function renderList(elements) {
|
||||
const { monthListEl, monthCountEl, listTitleEl } = elements;
|
||||
if (!monthListEl) {
|
||||
@@ -601,162 +463,46 @@
|
||||
}
|
||||
}
|
||||
|
||||
function associationSearchText(associations) {
|
||||
if (!associations || typeof associations !== "object") {
|
||||
return "";
|
||||
}
|
||||
|
||||
const tarotAliases = associations.tarotCard && typeof getTarotCardSearchAliases === "function"
|
||||
? getTarotCardSearchAliases(associations.tarotCard, { trumpNumber: associations.tarotTrumpNumber })
|
||||
: [];
|
||||
function getCalendarDataContext() {
|
||||
return {
|
||||
state,
|
||||
normalizeText,
|
||||
normalizeSearchValue,
|
||||
normalizeMinorTarotCardName,
|
||||
getTarotCardSearchAliases,
|
||||
addDays,
|
||||
buildSignDateBounds,
|
||||
formatDateLabel,
|
||||
formatIsoDate,
|
||||
getDaysInMonth,
|
||||
resolveCalendarDayToGregorian,
|
||||
resolveHolidayGregorianDate
|
||||
};
|
||||
}
|
||||
|
||||
return [
|
||||
associations.planetId,
|
||||
associations.zodiacSignId,
|
||||
associations.numberValue,
|
||||
associations.tarotCard,
|
||||
associations.tarotTrumpNumber,
|
||||
...tarotAliases,
|
||||
associations.godId,
|
||||
associations.godName,
|
||||
associations.hebrewLetterId,
|
||||
associations.kabbalahPathNumber,
|
||||
associations.iChingPlanetaryInfluence
|
||||
].filter(Boolean).join(" ");
|
||||
function buildDecanTarotRowsForMonth(month) {
|
||||
return calendarDataUi.buildDecanTarotRowsForMonth(getCalendarDataContext(), month);
|
||||
}
|
||||
|
||||
function getMonthDayLinkRows(month) {
|
||||
return calendarDataUi.getMonthDayLinkRows(getCalendarDataContext(), month);
|
||||
}
|
||||
|
||||
function eventSearchText(event) {
|
||||
return normalizeSearchValue([
|
||||
event?.name,
|
||||
event?.date,
|
||||
event?.dateRange,
|
||||
event?.description,
|
||||
associationSearchText(event?.associations)
|
||||
].filter(Boolean).join(" "));
|
||||
return calendarDataUi.eventSearchText(getCalendarDataContext(), event);
|
||||
}
|
||||
|
||||
function holidaySearchText(holiday) {
|
||||
return normalizeSearchValue([
|
||||
holiday?.name,
|
||||
holiday?.kind,
|
||||
holiday?.date,
|
||||
holiday?.dateRange,
|
||||
holiday?.dateText,
|
||||
holiday?.monthDayStart,
|
||||
holiday?.calendarId,
|
||||
holiday?.description,
|
||||
associationSearchText(holiday?.associations)
|
||||
].filter(Boolean).join(" "));
|
||||
return calendarDataUi.holidaySearchText(getCalendarDataContext(), holiday);
|
||||
}
|
||||
|
||||
function buildHolidayList(month) {
|
||||
const calendarId = state.selectedCalendar;
|
||||
const monthOrder = Number(month?.order);
|
||||
|
||||
const fromRepo = state.calendarHolidays.filter((holiday) => {
|
||||
const holidayCalendarId = normalizeText(holiday?.calendarId).toLowerCase();
|
||||
if (holidayCalendarId !== calendarId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const isDirectMonthMatch = normalizeText(holiday?.monthId).toLowerCase() === normalizeText(month?.id).toLowerCase();
|
||||
if (isDirectMonthMatch) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (calendarId === "gregorian" && holiday?.dateRule && Number.isFinite(monthOrder)) {
|
||||
const computedDate = resolveHolidayGregorianDate(holiday);
|
||||
return computedDate instanceof Date
|
||||
&& !Number.isNaN(computedDate.getTime())
|
||||
&& (computedDate.getMonth() + 1) === Math.trunc(monthOrder);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (fromRepo.length) {
|
||||
return [...fromRepo].sort((left, right) => {
|
||||
const leftDate = resolveHolidayGregorianDate(left);
|
||||
const rightDate = resolveHolidayGregorianDate(right);
|
||||
const leftDay = Number.isFinite(Number(left?.day))
|
||||
? Number(left.day)
|
||||
: ((leftDate instanceof Date && !Number.isNaN(leftDate.getTime())) ? leftDate.getDate() : NaN);
|
||||
const rightDay = Number.isFinite(Number(right?.day))
|
||||
? Number(right.day)
|
||||
: ((rightDate instanceof Date && !Number.isNaN(rightDate.getTime())) ? rightDate.getDate() : NaN);
|
||||
if (Number.isFinite(leftDay) && Number.isFinite(rightDay) && leftDay !== rightDay) {
|
||||
return leftDay - rightDay;
|
||||
}
|
||||
return normalizeText(left?.name).localeCompare(normalizeText(right?.name));
|
||||
});
|
||||
}
|
||||
|
||||
const seen = new Set();
|
||||
const ordered = [];
|
||||
|
||||
(month?.holidayIds || []).forEach((holidayId) => {
|
||||
const holiday = state.holidays.find((item) => item.id === holidayId);
|
||||
if (holiday && !seen.has(holiday.id)) {
|
||||
seen.add(holiday.id);
|
||||
ordered.push(holiday);
|
||||
}
|
||||
});
|
||||
|
||||
state.holidays.forEach((holiday) => {
|
||||
if (holiday?.monthId === month.id && !seen.has(holiday.id)) {
|
||||
seen.add(holiday.id);
|
||||
ordered.push(holiday);
|
||||
}
|
||||
});
|
||||
|
||||
return ordered;
|
||||
return calendarDataUi.buildHolidayList(getCalendarDataContext(), month);
|
||||
}
|
||||
|
||||
function buildMonthSearchText(month) {
|
||||
const monthHolidays = buildHolidayList(month);
|
||||
const holidayText = monthHolidays.map((holiday) => holidaySearchText(holiday)).join(" ");
|
||||
|
||||
if (state.selectedCalendar === "gregorian") {
|
||||
const events = Array.isArray(month?.events) ? month.events : [];
|
||||
return normalizeSearchValue([
|
||||
month?.name,
|
||||
month?.id,
|
||||
month?.start,
|
||||
month?.end,
|
||||
month?.coreTheme,
|
||||
month?.seasonNorth,
|
||||
month?.seasonSouth,
|
||||
associationSearchText(month?.associations),
|
||||
events.map((event) => eventSearchText(event)).join(" "),
|
||||
holidayText
|
||||
].filter(Boolean).join(" "));
|
||||
}
|
||||
|
||||
const wheelAssocText = month?.associations
|
||||
? [
|
||||
Array.isArray(month.associations.themes) ? month.associations.themes.join(" ") : "",
|
||||
Array.isArray(month.associations.deities) ? month.associations.deities.join(" ") : "",
|
||||
month.associations.element,
|
||||
month.associations.direction
|
||||
].filter(Boolean).join(" ")
|
||||
: "";
|
||||
|
||||
return normalizeSearchValue([
|
||||
month?.name,
|
||||
month?.id,
|
||||
month?.nativeName,
|
||||
month?.meaning,
|
||||
month?.season,
|
||||
month?.description,
|
||||
month?.zodiacSign,
|
||||
month?.tribe,
|
||||
month?.element,
|
||||
month?.type,
|
||||
month?.date,
|
||||
month?.hebrewLetter,
|
||||
holidayText,
|
||||
wheelAssocText
|
||||
].filter(Boolean).join(" "));
|
||||
return calendarDataUi.buildMonthSearchText(getCalendarDataContext(), month);
|
||||
}
|
||||
|
||||
function matchesSearch(searchText) {
|
||||
|
||||
Reference in New Issue
Block a user