Add NFC chore submission feature and enhance family settings
- 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.
This commit is contained in:
+42
-1
@@ -206,6 +206,15 @@ if ($editChore) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="chore_anyone_can_complete" <?= $editChore && !empty($editChore['anyone_can_complete']) ? 'checked' : '' ?>>
|
||||
<label class="form-check-label" for="chore_anyone_can_complete">
|
||||
Allow anyone to complete this chore using their own NFC/person token.
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label" for="chore_list_type">Checklist / list type</label>
|
||||
<select class="form-select" id="chore_list_type">
|
||||
@@ -253,6 +262,8 @@ if ($editChore) {
|
||||
$cid = htmlspecialchars($c['id'] ?? '', ENT_QUOTES, 'UTF-8');
|
||||
$assignees = $c['assignee_ids'] ?? [];
|
||||
$isAssignee = $actorId !== '' && is_array($assignees) && in_array((string) $actorId, $assignees, true);
|
||||
$canAnyoneSubmit = !empty($c['anyone_can_complete']);
|
||||
$canSubmit = $isAssignee || ($activePerson !== null && $canAnyoneSubmit);
|
||||
$canEdit = $activePerson && ((string) ($c['author_id'] ?? '') === (string) $actorId || $canReview);
|
||||
$pending = is_array($c['pending_submission'] ?? null);
|
||||
?>
|
||||
@@ -275,7 +286,27 @@ if ($editChore) {
|
||||
<?php if ($pending): ?>
|
||||
<span class="badge text-bg-warning">Waiting for approval</span>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($c['anyone_can_complete'])): ?>
|
||||
<span class="badge text-bg-info">Anyone can complete</span>
|
||||
<?php endif; ?>
|
||||
</p>
|
||||
<?php if ($canReview): ?>
|
||||
<?php $nfcMeta = is_array($c['nfc'] ?? null) ? $c['nfc'] : []; ?>
|
||||
<p class="small text-muted mb-2">
|
||||
NFC:
|
||||
<?php if (!empty($nfcMeta['enabled'])): ?>
|
||||
<span class="badge text-bg-success">Enabled</span>
|
||||
<?php elseif (!empty($nfcMeta['token_hash'])): ?>
|
||||
<span class="badge text-bg-secondary">Disabled</span>
|
||||
<?php else: ?>
|
||||
<span class="badge text-bg-light text-dark border">Not generated</span>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($nfcMeta['last_used_at'])): ?>
|
||||
<span class="ms-1">Last used <?= sanitizeInput((string) $nfcMeta['last_used_at']) ?></span>
|
||||
<?php endif; ?>
|
||||
</p>
|
||||
<p class="small text-muted mb-2">HoH setup: generate links, write each person link to their card/tag, label it, then test one scan.</p>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($c['lists']) && is_array($c['lists'])): ?>
|
||||
<p class="small text-muted mb-1"><strong>Steps</strong> (reference — use the button below when you’re done)</p>
|
||||
<?php endif; ?>
|
||||
@@ -291,7 +322,7 @@ if ($editChore) {
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
<div class="d-flex flex-wrap gap-2 mt-auto align-items-center">
|
||||
<?php if ($isAssignee && !$pending): ?>
|
||||
<?php if ($canSubmit && !$pending): ?>
|
||||
<button type="button" class="btn btn-sm btn-success btn-chore-submit" data-id="<?= $cid ?>">Submit for approval</button>
|
||||
<?php elseif ($activePerson !== null && !$pending && !$isAssignee): ?>
|
||||
<?php
|
||||
@@ -306,7 +337,17 @@ if ($editChore) {
|
||||
<?php if ($canEdit): ?>
|
||||
<a class="btn btn-sm btn-outline-primary" href="?tab=chores&edit=<?= $cid ?>">Edit</a>
|
||||
<?php endif; ?>
|
||||
<?php if ($canReview): ?>
|
||||
<button type="button" class="btn btn-sm btn-outline-dark btn-chore-nfc-generate" data-id="<?= $cid ?>">Generate NFC links</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary btn-chore-nfc-toggle" data-id="<?= $cid ?>" data-enable="<?= !empty(($c['nfc']['enabled'] ?? false)) ? '0' : '1' ?>">
|
||||
<?= !empty(($c['nfc']['enabled'] ?? false)) ? 'Disable NFC' : 'Enable NFC' ?>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php if ($canReview): ?>
|
||||
<div class="alert d-none mt-2 p-2 small chore-nfc-feedback" id="chore_nfc_feedback_<?= $cid ?>"></div>
|
||||
<div class="d-none mt-2 chore-nfc-links" id="chore_nfc_links_<?= $cid ?>"></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -164,10 +164,37 @@ $permanenceOptions = [
|
||||
value="<?= (int) ($familySettings['week_starts_on'] ?? 0) ?>"
|
||||
<?= !$canManage ? 'disabled' : '' ?>>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="nfc_base_url">NFC base URL override (optional)</label>
|
||||
<input class="form-control" id="nfc_base_url" name="nfc_base_url" placeholder="https://your-domain/familyHub"
|
||||
value="<?= sanitizeInput($familySettings['nfc_base_url'] ?? '') ?>"
|
||||
<?= !$canManage ? 'disabled' : '' ?>>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="nfc_scan_cooldown_seconds">NFC scan cooldown seconds</label>
|
||||
<input type="number" class="form-control" id="nfc_scan_cooldown_seconds" name="nfc_scan_cooldown_seconds" min="0" max="600"
|
||||
value="<?= (int) ($familySettings['nfc_scan_cooldown_seconds'] ?? 0) ?>"
|
||||
<?= !$canManage ? 'disabled' : '' ?>>
|
||||
</div>
|
||||
<div class="col-md-6 d-flex align-items-end">
|
||||
<div class="form-check mb-2">
|
||||
<input class="form-check-input" type="checkbox" id="nfc_show_confirmation" name="nfc_show_confirmation" value="1"
|
||||
<?= !empty($familySettings['nfc_show_confirmation']) ? 'checked' : '' ?>
|
||||
<?= !$canManage ? 'disabled' : '' ?>>
|
||||
<label class="form-check-label" for="nfc_show_confirmation">Show NFC confirmation page after scan</label>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($canManage): ?>
|
||||
<div class="col-12">
|
||||
<button type="submit" class="btn btn-primary">Save chore economy</button>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="small text-muted mb-2">Emergency NFC actions</div>
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
<button type="button" class="btn btn-outline-warning btn-sm" id="btnDisableAllChoreNfc">Disable all chore NFC links</button>
|
||||
<button type="button" class="btn btn-outline-danger btn-sm" id="btnRotateAllPersonNfcTokens">Rotate all person NFC tokens</button>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="col-12">
|
||||
<div class="alert d-none" id="familySettingsFeedback" role="status"></div>
|
||||
@@ -266,6 +293,7 @@ $permanenceOptions = [
|
||||
<th>Name</th>
|
||||
<th>Role</th>
|
||||
<th class="text-end">Balance</th>
|
||||
<?php if ($canManage): ?><th>NFC submit token</th><?php endif; ?>
|
||||
<?php if ($canManage): ?><th></th><?php endif; ?>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -276,6 +304,9 @@ $permanenceOptions = [
|
||||
<td><?= sanitizeInput($p['role'] ?? '') ?></td>
|
||||
<td class="text-end"><?= sanitizeInput((string) ($p['currency_balance'] ?? 0)) ?> <?= sanitizeInput($familySettings['currency_symbol'] ?? '') ?></td>
|
||||
<?php if ($canManage): ?>
|
||||
<td class="text-nowrap">
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary btn-rotate-person-nfc-token" data-id="<?= htmlspecialchars($p['id'] ?? '', ENT_QUOTES, 'UTF-8') ?>" data-name="<?= htmlspecialchars((string) ($p['name'] ?? ''), ENT_QUOTES, 'UTF-8') ?>">Rotate token</button>
|
||||
</td>
|
||||
<td class="text-end text-nowrap">
|
||||
<?php if (($p['role'] ?? '') === ROLE_HEAD): ?>
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary btn-reset-pin" data-id="<?= htmlspecialchars($p['id'] ?? '', ENT_QUOTES, 'UTF-8') ?>">Reset PIN</button>
|
||||
|
||||
Reference in New Issue
Block a user