Phase 1: Infrastructure setup - Install next-intl and create basic i18n structure

- Install next-intl package
- Create LanguageProvider hook with localStorage persistence
- Create IntlProvider component for next-intl integration
- Create Providers wrapper component
- Update layout.tsx to include providers and set default lang to 'es'
- Create initial translation files (common.json) for es, en, ca
- Fix pre-existing TypeScript errors in various pages

All tests passing, build successful.
This commit is contained in:
counterweight 2025-12-25 21:50:34 +01:00
parent 1a47b3643f
commit f7553df05d
Signed by: counterweight
GPG key ID: 883EDBAA726BD96C
15 changed files with 940 additions and 22 deletions

View file

@ -4,6 +4,7 @@ import { useState } from "react";
import { invitesApi } from "../api";
import { PageLayout } from "../components/PageLayout";
import { StatusBadge } from "../components/StatusBadge";
import { EmptyState } from "../components/EmptyState";
import { useRequireAuth } from "../hooks/useRequireAuth";
import { useAsyncData } from "../hooks/useAsyncData";
import { components } from "../generated/api";
@ -49,9 +50,9 @@ export default function InvitesPage() {
};
const { READY, SPENT, REVOKED } = constants.inviteStatuses;
const readyInvites = invites.filter((i) => i.status === READY);
const spentInvites = invites.filter((i) => i.status === SPENT);
const revokedInvites = invites.filter((i) => i.status === REVOKED);
const readyInvites = (invites ?? []).filter((i) => i.status === READY);
const spentInvites = (invites ?? []).filter((i) => i.status === SPENT);
const revokedInvites = (invites ?? []).filter((i) => i.status === REVOKED);
return (
<PageLayout
@ -67,7 +68,7 @@ export default function InvitesPage() {
</p>
</div>
{invites.length === 0 ? (
{(invites?.length ?? 0) === 0 ? (
<EmptyState
message="You don't have any invites yet."
hint="Contact an admin if you need invite codes to share."