diff --git a/apps/web/src/App.tsx b/apps/web/src/App.tsx index 5555b30..448840c 100644 --- a/apps/web/src/App.tsx +++ b/apps/web/src/App.tsx @@ -12,6 +12,7 @@ import { OnboardingAllergensPage } from "./pages/onboarding/OnboardingAllergensP import { OnboardingDietPage } from "./pages/onboarding/OnboardingDietPage"; import { OnboardingHouseholdPage } from "./pages/onboarding/OnboardingHouseholdPage"; import { AccountSettingsPage } from "./pages/settings/AccountSettingsPage"; +import { CreditsPage } from "./pages/settings/CreditsPage"; import { HouseholdSettingsPage } from "./pages/settings/HouseholdSettingsPage"; import { PreferencesPage } from "./pages/settings/PreferencesPage"; import { UserPreferencesPage } from "./pages/settings/UserPreferencesPage"; @@ -25,8 +26,8 @@ import { UserPreferencesPage } from "./pages/settings/UserPreferencesPage"; * itself redirects to `/login` if needed. * * `/parametres/*` (compte/préférences alimentaires/foyer/préférences - * utilisateur) are the settings pages, reachable from the sidebar's bottom - * "Paramètres" menu and the account menu (see `AppLayout`) — nested under + * utilisateur/crédits) are the settings pages, reachable from the sidebar's + * bottom "Paramètres" menu and the account menu (see `AppLayout`) — nested under * `AppLayout` like every other authenticated section. `/foyer` is the old, * pre-split combined page's path; it now just redirects to * `/parametres/foyer` so an existing bookmark/link keeps working. @@ -61,6 +62,7 @@ export function App() { } /> } /> } /> + } /> } /> ` (none set their own), so these theme/recolor exactly like the hand-drawn set. */ +function FilledIcon({ children }: { children: ReactNode }) { + return ( + + ); +} + +/** Carrot (foodiconpack.com, CC BY 4.0 — see the credits page) — root vegetables, leafy greens, and produce generally (`PRODUITS_FRAIS`/`LEGUMES`). */ export function VegetableIcon() { return ( - - - - + + + ); } -/** Apple — `PRODUITS_FRAIS`/`FRUITS`. */ +/** Apple (foodiconpack.com, CC BY 4.0) — `PRODUITS_FRAIS`/`FRUITS`. */ export function FruitIcon() { return ( - - - - + + + + + + ); } -/** A leaf sprig — `PRODUITS_FRAIS`/`HERBES_FRAICHES`. */ +/** Basil sprig (foodiconpack.com, CC BY 4.0) — `PRODUITS_FRAIS`/`HERBES_FRAICHES`. */ export function HerbIcon() { return ( - - - - - - + + + ); } -/** A cut of meat — `BOUCHERIE_POISSONNERIE`/`VIANDES`. */ +/** Cut of beef (foodiconpack.com, CC BY 4.0) — `BOUCHERIE_POISSONNERIE`/`VIANDES`. */ export function MeatIcon() { return ( - - - - + + + + + + ); } -/** Drumstick — `BOUCHERIE_POISSONNERIE`/`VOLAILLES`. */ +/** Chicken (foodiconpack.com, CC BY 4.0) — `BOUCHERIE_POISSONNERIE`/`VOLAILLES`. */ export function PoultryIcon() { return ( - - - - - + + + + + ); } -/** Fish — `BOUCHERIE_POISSONNERIE`/`POISSONS`. */ +/** Salmon (foodiconpack.com, CC BY 4.0) — `BOUCHERIE_POISSONNERIE`/`POISSONS`. */ export function FishIcon() { return ( - - - - - + + + + + + ); } -/** Shrimp — `BOUCHERIE_POISSONNERIE`/`CRUSTACES_FRUITS_DE_MER`. */ +/** Shrimp (foodiconpack.com, CC BY 4.0) — `BOUCHERIE_POISSONNERIE`/`CRUSTACES_FRUITS_DE_MER`. */ export function ShellfishIcon() { return ( - - - - + + + + ); } -/** Wheat ear — grains, pasta, rice, flour (`EPICERIE_SECHE`/`FECULENTS`, and flours under `AIDES_CULINAIRES`/`BASES`). */ +/** Bowl of rice (foodiconpack.com, CC BY 4.0) — grains, pasta, rice, flour (`EPICERIE_SECHE`/`FECULENTS`, and flours under `AIDES_CULINAIRES`/`BASES`). */ export function GrainIcon() { return ( - - - - - - - + + + + + + + + + + + + + ); } -/** Bean pod — `EPICERIE_SECHE`/`LEGUMINEUSES`. */ +/** Chickpeas (foodiconpack.com, CC BY 4.0) — `EPICERIE_SECHE`/`LEGUMINEUSES`. */ export function LegumeIcon() { return ( - - - - - + + + + + + + + + + ); } -/** Acorn — nuts, seeds, dried fruit (`EPICERIE_SECHE`/`GRAINES_FRUITS_SECS`). */ +/** Almonds (foodiconpack.com, CC BY 4.0) — nuts, seeds, dried fruit (`EPICERIE_SECHE`/`GRAINES_FRUITS_SECS`). */ export function NutSeedIcon() { return ( - - - - + + + + + + + + + + ); } @@ -161,34 +195,46 @@ export function DoughIcon() { ); } -/** A glass of milk — `CREMERIE_FROMAGE`/`PRODUITS_LAITIERS` (non-cheese items). */ +/** Milk carton (foodiconpack.com, CC BY 4.0) — `CREMERIE_FROMAGE`/`PRODUITS_LAITIERS` (non-cheese items). */ export function MilkIcon() { return ( - - - - + + + + + ); } -/** A wedge of cheese with holes — `CREMERIE_FROMAGE`/`PRODUITS_LAITIERS` (cheese items). */ +/** Wedge of cheddar (foodiconpack.com, CC BY 4.0) — `CREMERIE_FROMAGE`/`PRODUITS_LAITIERS` (cheese items). */ export function CheeseIcon() { return ( - - - - - - + + + + + + + + + + + + + ); } -/** An egg — `CREMERIE_FROMAGE`/`OEUFS`. */ +/** Eggs (foodiconpack.com, CC BY 4.0) — `CREMERIE_FROMAGE`/`OEUFS`. */ export function EggIcon() { return ( - - - + + + + + + + ); } @@ -203,67 +249,69 @@ export function SproutIcon() { ); } -/** A shaker — dried spices/herbs (`CONDIMENTS_EPICES`/`EPICES`). */ +/** Cinnamon sticks (foodiconpack.com, CC BY 4.0) — dried spices/herbs (`CONDIMENTS_EPICES`/`EPICES`). */ export function SpiceIcon() { return ( - - - - - + + + + + + + ); } -/** A condiment jar — sauces, pickles, tinned/preserved goods (`CONDIMENTS_EPICES`/`SAUCES` and the `EPICERIE_SECHE`/`AUTRES` catch-all). */ +/** Honey jar (foodiconpack.com, CC BY 4.0) — sauces, pickles, tinned/preserved goods (`CONDIMENTS_EPICES`/`SAUCES` and the `EPICERIE_SECHE`/`AUTRES` catch-all). */ export function JarIcon() { return ( - - - - - + + + + ); } -/** A bottle — oils, vinegars (`CONDIMENTS_EPICES`/`ASSAISONNEMENTS`, the pourable subset). */ +/** Oil bottle (foodiconpack.com, CC BY 4.0) — oils, vinegars (`CONDIMENTS_EPICES`/`ASSAISONNEMENTS`, the pourable subset). */ export function BottleIcon() { return ( - - - - + + + + + ); } -/** A glass — juices, coffee/tea, cooking alcohols, water (`CONDIMENTS_EPICES`/`ASSAISONNEMENTS`'s drinkable subset). */ +/** Glass (foodiconpack.com, CC BY 4.0) — juices, coffee/tea, cooking alcohols, water (`CONDIMENTS_EPICES`/`ASSAISONNEMENTS`'s drinkable subset). */ export function DrinkIcon() { return ( - - - - + + + + + + ); } -/** A stockpot — broths, stocks, water bases (`AIDES_CULINAIRES`/`BASES`'s liquid-base subset). */ +/** Stockpot (foodiconpack.com, CC BY 4.0) — broths, stocks, water bases (`AIDES_CULINAIRES`/`BASES`'s liquid-base subset). */ export function StockPotIcon() { return ( - - - - - + + + ); } -/** A sugar cube — `AIDES_CULINAIRES`/`SUCRES`. */ +/** Sugar (foodiconpack.com, CC BY 4.0) — `AIDES_CULINAIRES`/`SUCRES`. */ export function SugarIcon() { return ( - - - - - + + + + + ); } diff --git a/apps/web/src/layouts/AppLayout.tsx b/apps/web/src/layouts/AppLayout.tsx index 664d5ea..e3aef78 100644 --- a/apps/web/src/layouts/AppLayout.tsx +++ b/apps/web/src/layouts/AppLayout.tsx @@ -6,6 +6,7 @@ import "./AppLayout.scss"; import { AccountIcon, ChevronLeftIcon, + CreditsIcon, DietPreferencesIcon, HouseholdIcon, PlanningIcon, @@ -38,6 +39,7 @@ const SETTINGS_ITEMS = [ { to: "/parametres/preferences", key: "preferences", Icon: DietPreferencesIcon }, { to: "/parametres/foyer", key: "household", Icon: HouseholdIcon }, { to: "/parametres/preferences-utilisateur", key: "userPreferences", Icon: UserPreferencesIcon }, + { to: "/parametres/credits", key: "credits", Icon: CreditsIcon }, ] as const; /** diff --git a/apps/web/src/layouts/nav-icons.tsx b/apps/web/src/layouts/nav-icons.tsx index 84d62b3..a028745 100644 --- a/apps/web/src/layouts/nav-icons.tsx +++ b/apps/web/src/layouts/nav-icons.tsx @@ -21,6 +21,7 @@ export { Leaf as DietPreferencesIcon, Home as HouseholdIcon, Palette as UserPreferencesIcon, + Info as CreditsIcon, ChevronLeft as ChevronLeftIcon, Star as FavoriteIcon, Globe as PublicIcon, diff --git a/apps/web/src/locales/fr/translation.json b/apps/web/src/locales/fr/translation.json index 2d0c7f0..60a11bb 100644 --- a/apps/web/src/locales/fr/translation.json +++ b/apps/web/src/locales/fr/translation.json @@ -78,7 +78,8 @@ "account": "Compte", "preferences": "Préférences alimentaires", "household": "Foyer", - "userPreferences": "Préférences utilisateur" + "userPreferences": "Préférences utilisateur", + "credits": "Crédits" } }, "accountMenu": { @@ -260,6 +261,14 @@ "SYSTEM": "Système" } }, + "credits": { + "title": "Crédits", + "icons": { + "title": "Icônes d'ingrédients", + "description": "La plupart des icônes d'ingrédients de l'application proviennent des collections gratuites « Common ingredient icons » et « Common Utensils » de Food Icon Pack, sous licence Creative Commons Attribution 4.0. Elles ont été recolorées pour s'adapter aux thèmes clair et sombre de l'application.", + "licenseLabel": "Licence CC BY 4.0" + } + }, "household": { "title": "Foyer", "form": { diff --git a/apps/web/src/pages/settings/CreditsPage.tsx b/apps/web/src/pages/settings/CreditsPage.tsx new file mode 100644 index 0000000..086d91d --- /dev/null +++ b/apps/web/src/pages/settings/CreditsPage.tsx @@ -0,0 +1,37 @@ +import { useTranslation } from "react-i18next"; +import "./settings-pages.scss"; + +/** + * Third-party attribution — routed at `/parametres/credits`. Exists solely + * to satisfy the CC BY 4.0 requirement on the ingredient icon set (see + * `features/recipes/ingredient-icons.tsx`'s `FilledIcon`-based components): + * most of it comes from foodiconpack.com's free "Common ingredient icons" + * and "Common Utensils" collections, which require crediting the source, + * linking the license, and noting that the icons were adapted (recolored + * to `currentColor` for theming, original size/style attributes dropped — + * see the generation note in `ingredient-icons.tsx`). Nothing else in the + * app currently needs a credits entry — grow this page if that changes. + */ +export function CreditsPage() { + const { t } = useTranslation(); + + return ( +
+

{t("credits.title")}

+ +
+

{t("credits.icons.title")}

+

{t("credits.icons.description")}

+

+ + foodiconpack.com + + {" — "} + + {t("credits.icons.licenseLabel")} + +

+
+
+ ); +}