Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions apps/admin/src/foster-families/db.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { prisma } from "#i/core/prisma.server";
import type { FosterFamilySearchParams } from "#i/foster-families/search-params";
import type {
FosterFamily,
FosterFamilyEmergencies,
FosterFamilyGarden,
FosterFamilyHousing,
Species,
Expand Down Expand Up @@ -266,6 +267,12 @@ export class FosterFamilyDbDelegate {
});
}

if (searchParams.emergencies.size > 0) {
where.push({
emergencies: { in: Array.from(searchParams.emergencies) },
});
}

if (searchParams.garden.size > 0) {
where.push({ garden: { in: Array.from(searchParams.garden) } });
}
Expand Down Expand Up @@ -338,6 +345,7 @@ export class FosterFamilyDbDelegate {

type DataCreate = {
address: string;
emergencies?: FosterFamilyEmergencies;
availability: FosterFamilyAvailability;
availabilityExpirationDate: Date | null;
city: string;
Expand All @@ -354,6 +362,7 @@ type DataCreate = {

type DataUpdate = {
address?: string;
emergencies?: FosterFamilyEmergencies;
availability?: FosterFamilyAvailability;
availabilityExpirationDate?: Date | null;
city?: string;
Expand Down
49 changes: 49 additions & 0 deletions apps/admin/src/foster-families/emergencies.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Icon } from "#i/generated/icon";
import { cn } from "@animeaux/core";
import { FosterFamilyEmergencies } from "@animeaux/prisma";
import type { Except } from "type-fest";

export const SORTED_EMERGENCIES = [
FosterFamilyEmergencies.YES,
FosterFamilyEmergencies.NO,
FosterFamilyEmergencies.UNKNOWN,
];

export const EMERGENCIES_TRANSLATION: Record<FosterFamilyEmergencies, string> =
{
[FosterFamilyEmergencies.NO]: "Non",
[FosterFamilyEmergencies.YES]: "Oui",
[FosterFamilyEmergencies.UNKNOWN]: "Inconnu",
};

export const ICON_BY_EMERGENCIES: Record<
FosterFamilyEmergencies,
React.ReactNode
> = {
[FosterFamilyEmergencies.NO]: <Icon href="icon-tree-slash-solid" />,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je vais te fournir les icons a utiliser ici 👌

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merci ! :)

Copy link
Copy Markdown
Member

@simonrelet simonrelet Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On va utiliser siren-on-solid.svg quand une FA accepte les urgences et celle là (siren-on-slash-solid.svg) sinon:

siren-on-slash

[FosterFamilyEmergencies.YES]: <Icon href="icon-tree-solid" />,
[FosterFamilyEmergencies.UNKNOWN]: <Icon href="icon-tree-question-solid" />,
};

export function EmergenciesIcon({
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je n'ai pas l'impression que ce composant soit utilisé.
Tu l'utilises quelque part ? 🤔

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effectivement... Je me suis basée sur le Form.Field pour les types de logements. Je vais le supprimer :)

emergencies,
className,
...props
}: Except<React.ComponentPropsWithoutRef<typeof Icon>, "href"> & {
emergencies: FosterFamilyEmergencies;
}) {
return (
<Icon
{...props}
href="icon-status-solid"
className={cn(ICON_CLASS_NAMES_BY_EMERGENCIES[emergencies], className)}
/>
);
}

const ICON_CLASS_NAMES_BY_EMERGENCIES: Record<FosterFamilyEmergencies, string> =
{
[FosterFamilyEmergencies.YES]: cn("text-green-600"),
[FosterFamilyEmergencies.NO]: cn("text-red-500"),
[FosterFamilyEmergencies.UNKNOWN]: cn("text-gray-800"),
};
36 changes: 36 additions & 0 deletions apps/admin/src/foster-families/filter-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ import {
AvailabilityIcon,
SORTED_AVAILABILITIES,
} from "#i/foster-families/availability";
import {
EMERGENCIES_TRANSLATION,
EmergenciesIcon,
SORTED_EMERGENCIES,
} from "#i/foster-families/emergencies";
import {
GARDEN_TRANSLATION,
HOUSING_TRANSLATION,
Expand Down Expand Up @@ -120,6 +125,37 @@ export function FosterFamilyFilters({
</ToggleInputList>
</Filters.Filter>

<Filters.Filter
value={FosterFamilySearchParams.keys.emergencies}
label="Accueil court terme et urgence"
count={fosterFamilySearchParams.emergencies.size}
hiddenContent={Array.from(fosterFamilySearchParams.emergencies).map(
(emergencies) => (
<input
key={emergencies}
type="hidden"
name={FosterFamilySearchParams.keys.emergencies}
value={emergencies}
/>
),
)}
>
<ToggleInputList>
{SORTED_EMERGENCIES.map((emergencies) => (
<ToggleInput
key={emergencies}
type="checkbox"
label={EMERGENCIES_TRANSLATION[emergencies]}
name={FosterFamilySearchParams.keys.emergencies}
value={emergencies}
icon={<EmergenciesIcon emergencies={emergencies} />}
checked={fosterFamilySearchParams.emergencies.has(emergencies)}
onChange={() => {}}
/>
))}
</ToggleInputList>
</Filters.Filter>

<Filters.Filter
value={FosterFamilySearchParams.keys.speciesToHost}
label="Espèce à accueillir"
Expand Down
41 changes: 41 additions & 0 deletions apps/admin/src/foster-families/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ import {
AVAILABILITY_TRANSLATION,
SORTED_AVAILABILITIES,
} from "#i/foster-families/availability";
import {
EMERGENCIES_TRANSLATION,
SORTED_EMERGENCIES,
} from "#i/foster-families/emergencies";
import {
GARDEN_TRANSLATION,
HOUSING_TRANSLATION,
Expand All @@ -27,6 +31,7 @@ import { FormDataDelegate } from "@animeaux/form-data";
import type { FosterFamily } from "@animeaux/prisma";
import {
FosterFamilyAvailability,
FosterFamilyEmergencies,
FosterFamilyGarden,
FosterFamilyHousing,
Species,
Expand All @@ -50,6 +55,7 @@ const actionSchema = zu.object({
comments: zu.string().trim(),
displayName: zu.string().trim().min(1, "Veuillez entrer un nom"),
email: zu.string().email("Veuillez entrer un email valide"),
emergencies: zu.nativeEnum(FosterFamilyEmergencies),
garden: zu.nativeEnum(FosterFamilyGarden),
housing: zu.nativeEnum(FosterFamilyHousing),
phone: zu
Expand All @@ -76,6 +82,7 @@ type DefaultFosterFamily = null | SerializeFrom<
Pick<
FosterFamily,
| "address"
| "emergencies"
| "availability"
| "availabilityExpirationDate"
| "city"
Expand Down Expand Up @@ -489,6 +496,10 @@ export function FosterFamilyForm({

<Separator />

<Emergencies defaultFosterFamily={defaultFosterFamily} />
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je mettrais bien ce champs juste après la disponibilité

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je fais la modif :)


<Separator />

<Form.Field>
<Form.Label htmlFor={ActionFormData.keys.comments}>
Commentaires privés
Expand Down Expand Up @@ -569,3 +580,33 @@ function GardenField({
</Form.Field>
);
}

function Emergencies({
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
function Emergencies({
function EmergenciesField({

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merci !

defaultFosterFamily,
}: {
defaultFosterFamily?: DefaultFosterFamily;
}) {
return (
<Form.Field>
<Form.Label>
Accepte les accueils court terme et d'urgence <RequiredStar />
</Form.Label>

<RadioInputList>
{SORTED_EMERGENCIES.map((emergencies) => (
<RadioInput
key={emergencies}
label={EMERGENCIES_TRANSLATION[emergencies]}
name={ActionFormData.keys.emergencies}
value={emergencies}
defaultChecked={
emergencies ===
(defaultFosterFamily?.emergencies ??
FosterFamilyEmergencies.UNKNOWN)
}
/>
))}
</RadioInputList>
</Form.Field>
);
}
8 changes: 8 additions & 0 deletions apps/admin/src/foster-families/search-params.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
FosterFamilyAvailability,
FosterFamilyEmergencies,
FosterFamilyGarden,
FosterFamilyHousing,
Species,
Expand All @@ -10,6 +11,7 @@ import { zu } from "@animeaux/zod-utils";
export const FosterFamilySearchParams = SearchParamsIO.create({
keys: {
availability: "a",
emergencies: "e",
displayName: "q",
garden: "garden",
housing: "housing",
Expand All @@ -24,6 +26,7 @@ export const FosterFamilySearchParams = SearchParamsIO.create({
return Schema.parse({
availability: SearchParamsIO.getValues(searchParams, keys.availability),
displayName: SearchParamsIO.getValue(searchParams, keys.displayName),
emergencies: SearchParamsIO.getValues(searchParams, keys.emergencies),
garden: SearchParamsIO.getValues(searchParams, keys.garden),
housing: SearchParamsIO.getValues(searchParams, keys.housing),
cities: SearchParamsIO.getValues(searchParams, keys.cities),
Expand All @@ -49,6 +52,8 @@ export const FosterFamilySearchParams = SearchParamsIO.create({

SearchParamsIO.setValue(searchParams, keys.displayName, data.displayName);

SearchParamsIO.setValues(searchParams, keys.emergencies, data.emergencies);

SearchParamsIO.setValues(searchParams, keys.garden, data.garden);

SearchParamsIO.setValues(searchParams, keys.housing, data.housing);
Expand Down Expand Up @@ -82,6 +87,9 @@ const Schema = zu.object({
zu.searchParams.nativeEnum(FosterFamilyAvailability),
),
displayName: zu.searchParams.string(),
emergencies: zu.searchParams.set(
zu.searchParams.nativeEnum(FosterFamilyEmergencies),
),
garden: zu.searchParams.set(zu.searchParams.nativeEnum(FosterFamilyGarden)),
housing: zu.searchParams.set(zu.searchParams.nativeEnum(FosterFamilyHousing)),
cities: zu.searchParams.set(zu.searchParams.string()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
fosterFamily: prisma.fosterFamily.findUnique({
where: { id: paramsResult.data.id },
select: {
emergencies: true,
address: true,
availability: true,
availabilityExpirationDate: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { Icon } from "#i/generated/icon";
import { joinReactNodes } from "@animeaux/core";
import {
FosterFamilyAvailability,
FosterFamilyEmergencies,
FosterFamilyGarden,
FosterFamilyHousing,
} from "@animeaux/prisma";
Expand Down Expand Up @@ -113,6 +114,12 @@ export function SituationCard() {
].join("")}
</Markdown>
</SimpleItem>

<SimpleItem icon={<Icon href="icon-hand-holding-heart-solid" />}>
<Markdown components={HIGHLIGHT_COMPONENTS}>
{[TEXT_BY_EMERGENCY[fosterFamily.emergencies]].join("")}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{[TEXT_BY_EMERGENCY[fosterFamily.emergencies]].join("")}
{TEXT_BY_EMERGENCY[fosterFamily.emergencies]}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merci !

</Markdown>
</SimpleItem>
</ItemList>
</Card.Content>
</Card>
Expand All @@ -131,3 +138,10 @@ const TEXT_BY_GARDEN: Record<FosterFamilyGarden, string> = {
[FosterFamilyGarden.UNKNOWN]: "",
[FosterFamilyGarden.YES]: ", avec **jardin**",
};

const TEXT_BY_EMERGENCY: Record<FosterFamilyEmergencies, string> = {
[FosterFamilyEmergencies.NO]: "Accueil court terme et urgence : **Non**",
[FosterFamilyEmergencies.YES]: "Accueil court terme et urgence : **Oui**",
[FosterFamilyEmergencies.UNKNOWN]:
"Accueil court terme et urgence : **Inconnu**",
};
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export async function action({ request, params }: ActionFunctionArgs) {
paramsResult.data.id,
{
address: formData.data.address,
emergencies: formData.data.emergencies,
availability: formData.data.availability,
availabilityExpirationDate:
formData.data.availabilityExpirationDate ?? null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
where: { id: paramsResult.data.id },
select: {
address: true,
emergencies: true,
availability: true,
availabilityExpirationDate: true,
city: true,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-- CreateEnum
CREATE TYPE "FosterFamilyEmergencies" AS ENUM ('NO', 'YES', 'UNKNOWN');

-- AlterTable
ALTER TABLE "FosterFamily" ADD COLUMN "emergencies" "FosterFamilyEmergencies" NOT NULL DEFAULT 'UNKNOWN';
7 changes: 3 additions & 4 deletions libs/prisma/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,9 @@
"download-all-data": "tsx -r dotenv-flow/config ./scripts/download-all-data.ts",
"lint": "run-p --continue-on-error --print-label lint:*",
"lint:types": "tsc --noEmit",
"migrate": "yarn prisma-env migrate dev",
"prisma-env": "node -r dotenv-flow/config ./node_modules/.bin/prisma",
"reset": "yarn prisma-env migrate reset -f",
"studio": "yarn prisma-env studio"
"migrate": "prisma migrate dev",
"reset": "prisma migrate reset -f",
"studio": "prisma studio"
},
"prisma": {
"seed": "tsx -r dotenv-flow/config ./scripts/seed-data.ts"
Expand Down
7 changes: 7 additions & 0 deletions libs/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ model FosterFamily {
updatedAt DateTime @updatedAt
activities Activity[]

emergencies FosterFamilyEmergencies @default(UNKNOWN)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Est-ce qu'il y a une raison particulière pour utiliser une enum à la place d'un boolean ? 🤔

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pas forcément, je me suis basée sur un exemple, il me semble que c'était celui des jardins 🤔

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok je vois. Pour emergencies on ne va pas avoir besoin d'UNKNOWN parce que c'est une décision qu'on prends nous, on ne dépends pas sur une FA pour avoir l'info. Tu peux passer le champs en boolean et utiliser false en valeur par défaut 👌

availability FosterFamilyAvailability @default(UNKNOWN)
availabilityExpirationDate DateTime?
comments String?
Expand All @@ -110,6 +111,12 @@ enum FosterFamilyAvailability {
UNKNOWN
}

enum FosterFamilyEmergencies {
NO
YES
UNKNOWN
}

enum FosterFamilyHousing {
FLAT
HOUSE
Expand Down
24 changes: 12 additions & 12 deletions libs/prisma/scripts/seed-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ import { DateTime } from "luxon";

const DEFAULT_PASSWORD = "NotASword1!";

const ACTIVE_ANIMAL_STATUS: Status[] = [
Status.OPEN_TO_ADOPTION,
Status.OPEN_TO_RESERVATION,
Status.RESERVED,
Status.RETIRED,
Status.UNAVAILABLE,
];

const NON_ACTIVE_ANIMAL_STATUS: Status[] = Object.values(Status).filter(
(status) => !ACTIVE_ANIMAL_STATUS.includes(status),
);

console.log("🌱 Seeding data...");

const prisma = new PrismaClient();
Expand Down Expand Up @@ -382,18 +394,6 @@ function createEventInput({
};
}

const ACTIVE_ANIMAL_STATUS: Status[] = [
Status.OPEN_TO_ADOPTION,
Status.OPEN_TO_RESERVATION,
Status.RESERVED,
Status.RETIRED,
Status.UNAVAILABLE,
];

const NON_ACTIVE_ANIMAL_STATUS: Status[] = Object.values(Status).filter(
(status) => !ACTIVE_ANIMAL_STATUS.includes(status),
);

async function seedAnimals() {
await Promise.all([
seeds.users,
Expand Down
Loading