Production deployment setup + feature complete

- Dockerfile + deploy.sh for Hetzner server
- Email verification via Better Auth + Resend
- Invite code flow (6-digit OTP, generate/join)
- Settlement share percent fix (payer vs debtor)
- OCR scanner fixes (date display, retry, viewfinder)
- app.json icon/splash/adaptive-icon configured
- iOS deployment target 15.5 (ML Kit requirement)
- DB migration 0014: household_invitations table

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
René Schober
2026-03-20 11:54:22 +01:00
parent 4e34270786
commit 9ddc7c6d7a
194 changed files with 55961 additions and 305 deletions

View File

@@ -0,0 +1,50 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { apiRequest } from "../lib/api-client";
import { useAuthStore } from "../stores/auth.store";
export type MonthStatus = {
id: string;
householdId: string;
month: string;
status: "open" | "closed";
closedAt: string | null;
closedBy: string | null;
finalAmount: number | null;
notes: string | null;
finalTransferId: string | null;
createdAt: string;
};
export function useMonthStatus(month: string) {
const activeHouseholdId = useAuthStore((s) => s.activeHouseholdId);
return useQuery({
queryKey: ["month-status", activeHouseholdId, month],
queryFn: () =>
apiRequest<{ status: MonthStatus }>(`/api/months/${month}/status`),
select: (data) => data.status,
enabled: !!activeHouseholdId,
});
}
export type CloseMonthInput = {
finalAmount: number;
toUserId: string;
notes?: string;
};
export function useCloseMonth(month: string) {
const queryClient = useQueryClient();
const activeHouseholdId = useAuthStore((s) => s.activeHouseholdId);
return useMutation({
mutationFn: (input: CloseMonthInput) =>
apiRequest<{ status: MonthStatus }>(`/api/months/${month}/close`, {
method: "POST",
body: JSON.stringify(input),
}),
onSuccess: () => {
void queryClient.invalidateQueries({ queryKey: ["month-status", activeHouseholdId, month] });
void queryClient.invalidateQueries({ queryKey: ["settlement-v2", activeHouseholdId, month] });
void queryClient.invalidateQueries({ queryKey: ["transactions", activeHouseholdId] });
},
});
}