feat: close final competitive gap — professional review workflow + multi-country (MY/SG/UK)
Closes the 4th and final gap from the competitive benchmark: the human-in-the-loop professional tier every commercial competitor pairs with their software. Deliberately NOT a marketplace or payment integration — a structured review-request status on each member's Wassiyah (not_requested -> requested -> reviewed, with reviewer name recorded), surfaced on the Mutawalli dashboard so nothing quietly ships as final without the legally-required review being flagged. Paired with a new whole-app jurisdiction setting since 'necessary in certain countries' only makes sense per-jurisdiction: - nf_families.jurisdiction (MY/SG/UK), owner-only to change — first UPDATE policy ever added to nf_families, which previously had none. - New Settings-tab jurisdiction selector (JurisdictionSetting.svelte). - Wassiyah tab and the draft will document now carry jurisdiction- specific legal notes: Wills Act 1959 + state Syariah (Malaysia), Wills Act 1838 + AMLA (Singapore), Wills Act 1837 (UK). Singapore added as a full third jurisdiction option, not just a stub. - Zakat calculator's currency label and Nisab default now follow the family's jurisdiction (RM/SGD/GBP) instead of a hardcoded RM guess. Covered by e2e-jurisdiction-review.cjs (13/13). Full regression: 253/253 across all suites (2 reruns confirmed as pre-existing parallel-load flakes, not regressions).
This commit is contained in:
@@ -234,6 +234,29 @@ export async function listAllWassiyahForFamily(familyId) {
|
||||
return data || [];
|
||||
}
|
||||
|
||||
// ── Professional review workflow — a structured status, not a marketplace.
|
||||
// Any family member can request review of their own Wassiyah; anyone (in
|
||||
// practice the mutawalli/agent, coordinating with an actual lawyer outside
|
||||
// the app) can mark it reviewed once done.
|
||||
export async function requestWassiyahReview(familyId, authorId) {
|
||||
const { error } = await supabase.from('nf_wassiyah_settings').upsert({
|
||||
family_id: familyId, author_id: authorId, review_status: 'requested', requested_at: new Date().toISOString(), updated_at: new Date().toISOString()
|
||||
}, { onConflict: 'family_id,author_id' });
|
||||
if (error) throw error;
|
||||
}
|
||||
export async function markWassiyahReviewed(familyId, authorId, reviewerName) {
|
||||
const { error } = await supabase.from('nf_wassiyah_settings').upsert({
|
||||
family_id: familyId, author_id: authorId, review_status: 'reviewed', reviewer_name: reviewerName, reviewed_at: new Date().toISOString(), updated_at: new Date().toISOString()
|
||||
}, { onConflict: 'family_id,author_id' });
|
||||
if (error) throw error;
|
||||
}
|
||||
/** For the mutawalli dashboard: every family member's Wassiyah settings (jurisdiction, review status). */
|
||||
export async function listAllWassiyahSettingsForFamily(familyId) {
|
||||
const { data, error } = await supabase.from('nf_wassiyah_settings').select('*').eq('family_id', familyId);
|
||||
if (error) throw error;
|
||||
return data || [];
|
||||
}
|
||||
|
||||
// ── Per-member death trigger — the mutawalli/owner fires it for a specific
|
||||
// member, never the member themselves (enforced by RLS, not just the UI). ──
|
||||
export async function getMemberTrigger(memberId, familyId) {
|
||||
|
||||
Reference in New Issue
Block a user