- Introduced NFC support for chore submissions, allowing specific person credit after Head of Household approval. - Updated family settings to include NFC base URL, scan cooldown, and confirmation page options. - Enhanced chore management with options for anyone to complete chores and NFC link generation. - Improved API endpoints for handling NFC tokens and chore submissions. - Updated readme to reflect new NFC features and settings.
138 lines
4.2 KiB
PHP
138 lines
4.2 KiB
PHP
<?php
|
|
|
|
require_once __DIR__ . '/db.php';
|
|
|
|
/**
|
|
* @return list<string>
|
|
*/
|
|
function familyHubUsTimezoneIdentifiers(): array {
|
|
$ids = DateTimeZone::listIdentifiers(DateTimeZone::PER_COUNTRY, 'US');
|
|
if (is_array($ids) && $ids !== []) {
|
|
sort($ids);
|
|
return array_values($ids);
|
|
}
|
|
return [
|
|
'Pacific/Honolulu',
|
|
'America/Anchorage',
|
|
'America/Los_Angeles',
|
|
'America/Phoenix',
|
|
'America/Denver',
|
|
'America/Chicago',
|
|
'America/New_York',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @return array<string, mixed>
|
|
*/
|
|
function familySettingsDefaultsRaw(): array {
|
|
return [
|
|
'currency_symbol' => '★',
|
|
'currency_name' => 'Stars',
|
|
'currency_permanence' => 'permanent',
|
|
'timezone' => 'America/New_York',
|
|
'week_starts_on' => 0,
|
|
'calendar_two_way_google' => false,
|
|
'calendar_bill_days' => [],
|
|
'nfc_base_url' => '',
|
|
'nfc_show_confirmation' => true,
|
|
'nfc_scan_cooldown_seconds' => 0,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @param mixed $raw
|
|
* @return list<array{dayOfMonth: int, title: string}>
|
|
*/
|
|
function normalizeCalendarBillDaysRaw($raw): array {
|
|
if (!is_array($raw)) {
|
|
return [];
|
|
}
|
|
$out = [];
|
|
foreach ($raw as $row) {
|
|
if (!is_array($row)) {
|
|
continue;
|
|
}
|
|
$d = isset($row['dayOfMonth']) ? (int) $row['dayOfMonth'] : 0;
|
|
$title = trim((string) ($row['title'] ?? ''));
|
|
if ($d < 1 || $d > 31 || $title === '') {
|
|
continue;
|
|
}
|
|
$out[] = ['dayOfMonth' => $d, 'title' => $title];
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
function normalizeTimezoneToUs(string $tz, array $allowed): string {
|
|
$tz = trim($tz);
|
|
if ($tz !== '' && in_array($tz, $allowed, true)) {
|
|
return $tz;
|
|
}
|
|
return 'America/New_York';
|
|
}
|
|
|
|
/**
|
|
* Apply defaults and normalize timezone / calendar fields after merge with stored JSON.
|
|
*
|
|
* @param array<string, mixed> $s
|
|
* @return array<string, mixed>
|
|
*/
|
|
function normalizeLoadedFamilySettings(array $s): array {
|
|
$allowed = familyHubUsTimezoneIdentifiers();
|
|
$s['timezone'] = normalizeTimezoneToUs((string) ($s['timezone'] ?? ''), $allowed);
|
|
$v = $s['calendar_two_way_google'] ?? false;
|
|
$s['calendar_two_way_google'] = $v === true || $v === 1 || $v === '1' || $v === 'true';
|
|
$s['calendar_bill_days'] = normalizeCalendarBillDaysRaw($s['calendar_bill_days'] ?? []);
|
|
$s['nfc_base_url'] = trim((string) ($s['nfc_base_url'] ?? ''));
|
|
$showConfirmation = $s['nfc_show_confirmation'] ?? true;
|
|
$s['nfc_show_confirmation'] = $showConfirmation === true || $showConfirmation === 1 || $showConfirmation === '1' || $showConfirmation === 'true';
|
|
$cooldown = (int) ($s['nfc_scan_cooldown_seconds'] ?? 0);
|
|
$s['nfc_scan_cooldown_seconds'] = max(0, min(600, $cooldown));
|
|
return $s;
|
|
}
|
|
|
|
function defaultFamilySettings(): array {
|
|
return normalizeLoadedFamilySettings(familySettingsDefaultsRaw());
|
|
}
|
|
|
|
function loadFamilySettings(): array {
|
|
$raw = readJsonFile('family_settings.json');
|
|
$merged = familySettingsDefaultsRaw();
|
|
if (is_array($raw)) {
|
|
$merged = array_merge($merged, $raw);
|
|
}
|
|
return normalizeLoadedFamilySettings($merged);
|
|
}
|
|
|
|
/**
|
|
* Base app URL (without trailing slash) used for externally shared links.
|
|
*/
|
|
function familyHubAppUrl(array $familySettings): string {
|
|
$base = trim((string) ($familySettings['nfc_base_url'] ?? ''));
|
|
if ($base !== '') {
|
|
return rtrim($base, '/');
|
|
}
|
|
$https = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off';
|
|
$scheme = $https ? 'https' : 'http';
|
|
$host = trim((string) ($_SERVER['HTTP_HOST'] ?? 'localhost'));
|
|
$script = trim((string) ($_SERVER['SCRIPT_NAME'] ?? '/index.php'));
|
|
$dir = rtrim(str_replace('\\', '/', dirname($script)), '/');
|
|
if ($dir === '' || $dir === '.') {
|
|
$dir = '';
|
|
}
|
|
if (substr($dir, -4) === '/api') {
|
|
$dir = substr($dir, 0, -4);
|
|
}
|
|
return $scheme . '://' . $host . $dir;
|
|
}
|
|
|
|
/**
|
|
* Tab label: symbol + name (e.g. "★ Stars").
|
|
*/
|
|
function currencyTabLabel(array $familySettings): string {
|
|
$sym = trim((string) ($familySettings['currency_symbol'] ?? ''));
|
|
$name = trim((string) ($familySettings['currency_name'] ?? ''));
|
|
$label = trim($sym . ' ' . $name);
|
|
return $label !== '' ? $label : 'Currency';
|
|
}
|