update some minor ux issues
This commit is contained in:
@@ -21,8 +21,12 @@
|
||||
let disabled = $derived(!!data.famAccess?.disabled);
|
||||
let accessReason = $derived(data.famAccess?.reason || '');
|
||||
// Settings stays usable while paused so admins can apply a code / manage billing.
|
||||
let hasAuth = $derived(!!data.session);
|
||||
let locked = $derived(disabled && !page.url.pathname.endsWith('/settings'));
|
||||
|
||||
$effect(() => {
|
||||
console.log(data, page.url.pathname.includes('/join'), locked);
|
||||
});
|
||||
// ── Post-checkout activation (event-driven) ──
|
||||
// Landing with ?checkout=return: if the webhook has already landed we show
|
||||
// the welcome notice; otherwise show an "activating" state and wait for the
|
||||
@@ -89,16 +93,22 @@
|
||||
|
||||
function accessMessage(reason: string, parent: boolean) {
|
||||
const map: Record<string, string> = {
|
||||
code_expired: parent ? 'Access paused — your code has expired. Add a new one.' : 'Access paused.',
|
||||
code_expired: parent
|
||||
? 'Access paused — your code has expired. Add a new one.'
|
||||
: 'Access paused.',
|
||||
code_disabled: parent ? 'Access paused — your access code was disabled.' : 'Access paused.',
|
||||
subscription_inactive: parent ? 'Access paused — check your subscription payment.' : 'Access paused.',
|
||||
canceled: parent ? 'Access paused — renew your subscription or add a code.' : 'Access paused.',
|
||||
subscription_inactive: parent
|
||||
? 'Access paused — check your subscription payment.'
|
||||
: 'Access paused.',
|
||||
canceled: parent
|
||||
? 'Access paused — renew your subscription or add a code.'
|
||||
: 'Access paused.',
|
||||
no_access: parent ? 'Access paused — add an access code to get started.' : 'Access paused.'
|
||||
};
|
||||
return map[reason] || 'Access paused.';
|
||||
}
|
||||
|
||||
// Claim toast watcher (admin only)
|
||||
// Claim toast watcher (admin only)
|
||||
let claimToast = $state('');
|
||||
let prevClaimedIds = new Set<string>();
|
||||
let mounted = false;
|
||||
@@ -173,25 +183,28 @@
|
||||
</TopNav>
|
||||
<main class="app-main">
|
||||
<div class="page-wrap">
|
||||
<div class="page-content" class:locked>{@render children()}</div>
|
||||
{#if locked}
|
||||
<div class="disabled-overlay">
|
||||
<div class="disabled-card">
|
||||
{#if activating}
|
||||
<div class="spinner" aria-hidden="true"></div>
|
||||
<strong>Activating your subscription…</strong>
|
||||
<span>Payment received — this usually only takes a few seconds.</span>
|
||||
{:else}
|
||||
<strong>Access paused</strong>
|
||||
<span>
|
||||
{isParent
|
||||
? 'Add an access code or resume your subscription to keep using FamChore.'
|
||||
: 'Your family access is paused.'}
|
||||
</span>
|
||||
{/if}
|
||||
<div class="page-content" class:locked>{@render children()}</div>
|
||||
|
||||
{#if locked}
|
||||
<div class="disabled-overlay">
|
||||
<div class="disabled-card">
|
||||
{#if !hasAuth}
|
||||
<h2>You need to be logged in to view this page</h2>
|
||||
{:else if activating}
|
||||
<div class="spinner" aria-hidden="true"></div>
|
||||
<strong>Activating your subscription…</strong>
|
||||
<span>Payment received — this usually only takes a few seconds.</span>
|
||||
{:else}
|
||||
<strong>Access paused</strong>
|
||||
<span>
|
||||
{isParent
|
||||
? 'Add an access code or resume your subscription to keep using FamChore.'
|
||||
: 'Your family access is paused.'}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</main>
|
||||
{#if claimToast}
|
||||
|
||||
@@ -13,10 +13,10 @@ export async function load(event) {
|
||||
s.crud.list('members', famId),
|
||||
s.crud.list('chore-templates', famId),
|
||||
s.crud.list('assigned-chores', famId),
|
||||
s.fam.weeklySummary(famId),
|
||||
s.fam.weeklySummary(famId)
|
||||
]);
|
||||
return { members, templates, assigned, summary };
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import {
|
||||
checkCircleIcon,
|
||||
revokeIcon,
|
||||
todoIcon,
|
||||
circleIcon,
|
||||
targetIcon,
|
||||
sunIcon,
|
||||
calendarIcon,
|
||||
@@ -19,6 +19,7 @@
|
||||
handCoinsIcon,
|
||||
moneyIcon,
|
||||
coinsIcon,
|
||||
walletIcon,
|
||||
chevronLeftIcon,
|
||||
chevronRightIcon
|
||||
} from '$lib/components/icons';
|
||||
@@ -578,6 +579,9 @@
|
||||
function headDay(): number {
|
||||
return headDate().getDate();
|
||||
}
|
||||
function headWeekday(): string {
|
||||
return headDate().toLocaleDateString(undefined, { weekday: 'long' });
|
||||
}
|
||||
function headMonth(): string {
|
||||
const d = headDate();
|
||||
return `${MONTHS[d.getMonth()]} ${d.getFullYear()}`;
|
||||
@@ -1078,6 +1082,7 @@
|
||||
</div>
|
||||
<div class="hero-date">
|
||||
<span class="hero-day">{headDay()}</span>
|
||||
<span class="hero-weekday">{headWeekday()}</span>
|
||||
<span class="hero-month">{headMonth()}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1259,7 +1264,7 @@
|
||||
{:else}
|
||||
{#each dailyPending as chore}
|
||||
<button class="chore" onclick={() => toggle(chore)} disabled={!!togglingIds}>
|
||||
<span class="checkbox empty"></span>
|
||||
<span class="checkbox">{@html circleIcon}</span>
|
||||
<span class="chore-name">{choreName(chore)}</span>
|
||||
<span class="chore-value">{chore.value} {chore.type}</span>
|
||||
</button>
|
||||
@@ -1276,7 +1281,7 @@
|
||||
{:else}
|
||||
{#each weeklyPending as chore}
|
||||
<button class="chore" onclick={() => toggle(chore)} disabled={!!togglingIds}>
|
||||
<span class="checkbox empty"></span>
|
||||
<span class="checkbox">{@html circleIcon}</span>
|
||||
<span class="chore-name">{choreName(chore)}</span>
|
||||
<span class="chore-value">{chore.value} {chore.type}</span>
|
||||
</button>
|
||||
@@ -1284,28 +1289,30 @@
|
||||
{#each memberTodos.filter((t) => !isTodoDone(t.id)) as todo}
|
||||
{@const urgency = todoUrgency(todo)}
|
||||
{#if todo.type === 'emoji'}
|
||||
<div
|
||||
class="chore todo-chore todo-display"
|
||||
<button
|
||||
class="chore todo-chore"
|
||||
class:todo-blue={urgency === 'blue'}
|
||||
class:todo-green={urgency === 'green'}
|
||||
class:todo-orange={urgency === 'orange'}
|
||||
class:todo-red={urgency === 'red'}
|
||||
class:todo-black={urgency === 'black'}
|
||||
onclick={() => toggle(todo)}
|
||||
disabled={!!togglingIds}
|
||||
>
|
||||
<span class="checkbox">{@html todoIcon}</span>
|
||||
<span class="checkbox">{@html circleIcon}</span>
|
||||
<span class="todo-main">
|
||||
<span class="chore-name">{todo.customName || 'Todo'}</span>
|
||||
{#if todo.completeBy}
|
||||
{#if todo.completeBy === todayChild}
|
||||
<span class="todo-due due-today">DUE TODAY!</span>
|
||||
{:else}
|
||||
<span class="todo-due">due {formatHumanDate(todo.completeBy)}</span>
|
||||
{#if todo.completeBy}
|
||||
{#if todo.completeBy === todayChild}
|
||||
<span class="todo-due due-today">DUE TODAY!</span>
|
||||
{:else}
|
||||
<span class="todo-due">due {formatHumanDate(todo.completeBy)}</span>
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
</span>
|
||||
<span class="todo-label">todo</span>
|
||||
<span class="chore-value">{todo.emoji || '🎯'}</span>
|
||||
</div>
|
||||
</button>
|
||||
{:else}
|
||||
<button
|
||||
class="chore todo-chore"
|
||||
@@ -1317,16 +1324,16 @@
|
||||
onclick={() => toggle(todo)}
|
||||
disabled={!!togglingIds}
|
||||
>
|
||||
<span class="checkbox">{@html todoIcon}</span>
|
||||
<span class="checkbox">{@html circleIcon}</span>
|
||||
<span class="todo-main">
|
||||
<span class="chore-name">{todo.customName || 'Todo'}</span>
|
||||
{#if todo.completeBy}
|
||||
{#if todo.completeBy === todayChild}
|
||||
<span class="todo-due due-today">DUE TODAY!</span>
|
||||
{:else}
|
||||
<span class="todo-due">due {formatHumanDate(todo.completeBy)}</span>
|
||||
{#if todo.completeBy}
|
||||
{#if todo.completeBy === todayChild}
|
||||
<span class="todo-due due-today">DUE TODAY!</span>
|
||||
{:else}
|
||||
<span class="todo-due">due {formatHumanDate(todo.completeBy)}</span>
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
</span>
|
||||
<span class="todo-label">todo</span>
|
||||
<span class="chore-value">
|
||||
@@ -1350,7 +1357,11 @@
|
||||
<button class="chore done" onclick={() => toggle(chore)} disabled={!!togglingIds}>
|
||||
<span class="checkbox">{@html checkCircleIcon}</span>
|
||||
<span class="chore-name">{choreName(chore)}</span>
|
||||
<span class="chore-value">{chore.value} {chore.type}</span>
|
||||
{#if chore.type === 'emoji'}
|
||||
<span class="chore-value">{chore.emoji || '🎯'}</span>
|
||||
{:else}
|
||||
<span class="chore-value">{chore.value} {chore.type}</span>
|
||||
{/if}
|
||||
</button>
|
||||
{/if}
|
||||
{/each}
|
||||
@@ -1362,7 +1373,7 @@
|
||||
<!-- WALLET / CLAIMS -->
|
||||
<div class="wallet">
|
||||
<div class="wallet-top">
|
||||
<span class="wallet-lbl">{@html moneyIcon} Wallet</span>
|
||||
<span class="wallet-lbl">{@html walletIcon} Wallet</span>
|
||||
{#if allTimeCash > 0 || allTimePoints > 0}
|
||||
<span class="wallet-total">
|
||||
<span class="wallet-cash">£{allTimeCash.toFixed(2)}</span>
|
||||
@@ -1906,6 +1917,11 @@
|
||||
font-weight: 600;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
}
|
||||
.hero-weekday {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
}
|
||||
.hero-progress {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -2018,8 +2034,9 @@
|
||||
}
|
||||
.hero-nav-btn.cur {
|
||||
flex: 1;
|
||||
background: #fff;
|
||||
color: #6d28d9;
|
||||
background: transparent;
|
||||
color: #fff;
|
||||
border: 1px solid rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
/* ── Kanban scroll for parent view cards ── */
|
||||
@@ -2334,17 +2351,6 @@
|
||||
opacity: 0.55;
|
||||
}
|
||||
}
|
||||
.todo-display {
|
||||
cursor: default;
|
||||
opacity: 0.85;
|
||||
}
|
||||
.todo-display:hover {
|
||||
transform: none;
|
||||
box-shadow: none;
|
||||
border-top-color: #e5e7eb;
|
||||
border-right-color: #e5e7eb;
|
||||
border-bottom-color: #e5e7eb;
|
||||
}
|
||||
.chore:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
@@ -2364,14 +2370,6 @@
|
||||
display: inline-block;
|
||||
vertical-align: -0.2em;
|
||||
}
|
||||
.checkbox.empty {
|
||||
display: inline-block;
|
||||
width: 1.15em;
|
||||
height: 1.15em;
|
||||
border: 2px solid currentColor;
|
||||
border-radius: 4px;
|
||||
vertical-align: -0.2em;
|
||||
}
|
||||
.chore-name {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
|
||||
Reference in New Issue
Block a user