Repeats, estimates, weekly review: completing a repeating task spawns the next occurrence; estimate chips + quick-add tokens (~30m, monthly); review screen with one-tap triage; server gains repeat column and applies its idempotent schema at boot
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
29
app/src/lib/review.ts
Normal file
29
app/src/lib/review.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
// Last-completed-review timestamp, local only — the review is a habit, not
|
||||
// synced data.
|
||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
|
||||
const KEY = "review_last_v1";
|
||||
|
||||
export async function getLastReview(): Promise<string | null> {
|
||||
return AsyncStorage.getItem(KEY);
|
||||
}
|
||||
|
||||
export async function markReviewed(): Promise<void> {
|
||||
await AsyncStorage.setItem(KEY, new Date().toISOString());
|
||||
}
|
||||
|
||||
export function daysSince(iso: string | null): number | null {
|
||||
if (!iso) return null;
|
||||
return Math.floor((Date.now() - new Date(iso).getTime()) / 86_400_000);
|
||||
}
|
||||
|
||||
/** [lastReviewIso, reload] — call reload on focus to pick up changes. */
|
||||
export function useLastReview(): [string | null, () => void] {
|
||||
const [last, setLast] = useState<string | null>(null);
|
||||
const reload = useCallback(() => {
|
||||
void getLastReview().then(setLast);
|
||||
}, []);
|
||||
useEffect(reload, [reload]);
|
||||
return [last, reload];
|
||||
}
|
||||
Reference in New Issue
Block a user