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
1 change: 1 addition & 0 deletions apps/admin/src/animals/status.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export function StatusIcon({
const CHIP_COLOR_STATUS_ICON_CLASS_NAMES: Record<ChipColor, string> = {
green: cn("text-green-600"),
black: cn("text-gray-800"),
grey: cn("text-gray-500"),
red: cn("text-red-500"),
blue: cn("text-blue-500"),
yellow: cn("text-yellow-400"),
Expand Down
11 changes: 10 additions & 1 deletion apps/admin/src/core/data-display/chip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ import { Icon } from "#i/generated/icon.js"

export type ChipVariant = "primary" | "secondary"

export type ChipColor = "black" | "blue" | "green" | "orange" | "red" | "yellow"
export type ChipColor =
| "black"
| "blue"
| "green"
| "grey"
| "orange"
| "red"
| "yellow"

export function Chip({
variant,
Expand Down Expand Up @@ -42,6 +49,7 @@ const COLOR_CLASS_NAME: Record<ChipVariant, Record<ChipColor, string>> = {
black: cn("bg-gray-800 text-white"),
blue: cn("bg-blue-500 text-white"),
green: cn("bg-green-600 text-white"),
grey: cn("bg-gray-500 text-white"),
orange: cn("bg-orange-500 text-white"),
red: cn("bg-red-500 text-white"),
yellow: cn("bg-yellow-400 text-gray-800"),
Expand All @@ -51,6 +59,7 @@ const COLOR_CLASS_NAME: Record<ChipVariant, Record<ChipColor, string>> = {
black: cn("bg-gray-100 text-gray-800"),
blue: cn("bg-blue-50 text-blue-500"),
green: cn("bg-green-50 text-green-600"),
grey: cn("bg-gray-100 text-gray-500"),
orange: cn("bg-orange-50 text-orange-500"),
red: cn("bg-red-50 text-red-500"),
yellow: cn("bg-yellow-50 text-yellow-700"),
Expand Down
6 changes: 5 additions & 1 deletion apps/admin/src/core/data-display/helper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Action } from "#i/core/actions.js"
import type { IconName } from "#i/generated/icon.js"
import { Icon } from "#i/generated/icon.js"

type HelperVariant = "error" | "info" | "success" | "warning"
type HelperVariant = "error" | "info" | "neutral" | "success" | "warning"

type BlockHelperProps = {
children?: React.ReactNode
Expand Down Expand Up @@ -34,6 +34,7 @@ export function BlockHelper({ children, icon, variant }: BlockHelperProps) {
const BLOCK_VARIANT_CLASS_NAME: Record<HelperVariant, string> = {
error: cn("border-red-100"),
info: cn("border-blue-100"),
neutral: cn("border-gray-100"),
success: cn("border-green-100"),
warning: cn("border-orange-100"),
}
Expand Down Expand Up @@ -76,6 +77,7 @@ export function InlineHelper({
const VARIANT_ACTION_COLOR: Record<HelperVariant, ActionColor> = {
error: "red",
info: "blue",
neutral: "gray",
success: "green",
warning: "orange",
}
Expand Down Expand Up @@ -113,13 +115,15 @@ export function DenseHelper({
const VARIANT_CLASS_NAME: Record<HelperVariant, string> = {
error: cn("bg-red-50 text-red-500"),
info: cn("bg-blue-50 text-blue-500"),
neutral: cn("bg-gray-200 text-gray-500"),
success: cn("bg-green-50 text-green-600"),
warning: cn("bg-orange-50 text-orange-500"),
}

const VARIANT_ICON: Record<HelperVariant, IconName> = {
error: "icon-circle-exclamation-solid",
info: "icon-circle-info-solid",
neutral: "icon-triangle-exclamation-solid",
success: "icon-circle-check-solid",
warning: "icon-triangle-exclamation-solid",
}
1 change: 1 addition & 0 deletions apps/admin/src/foster-families/db.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ type DataUpdate = {
email?: string
garden?: FosterFamilyGarden
housing?: FosterFamilyHousing
isArchived?: boolean
isBanned?: boolean
phone?: string
speciesAlreadyPresent?: Species[]
Expand Down
143 changes: 136 additions & 7 deletions apps/admin/src/routes/_layout.foster-families.$id._index/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
garden: true,
housing: true,
id: true,
isArchived: true,
isBanned: true,
phone: true,
speciesAlreadyPresent: true,
Expand Down Expand Up @@ -125,12 +126,24 @@ export const meta: MetaFunction<typeof loader> = ({ data }) => {
return [{ title: getPageTitle(fosterFamily.displayName) }]
}

const SharedActionFormData = FormDataDelegate.create(
zu.object({
action: zu.union([zu.literal("ARCHIVE"), zu.literal("BAN")]),
}),
)

const BanActionFormData = FormDataDelegate.create(
zu.object({
isBanned: zu.checkbox(),
}),
)

const ArchiveActionFormData = FormDataDelegate.create(
zu.object({
isArchived: zu.checkbox(),
}),
)

export async function action({ request, params }: ActionFunctionArgs) {
const currentUser = await db.currentUser.get(request, {
select: { id: true, groups: true },
Expand All @@ -153,9 +166,23 @@ export async function action({ request, params }: ActionFunctionArgs) {
})
}

return await actionBan({
const rawFormData = await request.formData()
const formData = SharedActionFormData.safeParse(rawFormData)
if (!formData.success) {
throw badRequest()
}

if (formData.data.action === "BAN") {
return await actionBan({
fosterFamilyId: paramsResult.data.id,
formData: rawFormData,
currentUser,
})
}

return await actionArchive({
fosterFamilyId: paramsResult.data.id,
request,
formData: rawFormData,
currentUser,
})
}
Expand Down Expand Up @@ -197,23 +224,55 @@ async function actionDelete({
throw redirect(Routes.fosterFamilies.toString())
}

async function actionArchive({
fosterFamilyId,
currentUser,
formData,
}: {
fosterFamilyId: FosterFamily["id"]
currentUser: { id: string }
formData: FormData
}) {
const parsedData = ArchiveActionFormData.safeParse(formData)
if (!parsedData.success) {
throw badRequest()
}

try {
await db.fosterFamily.update(
fosterFamilyId,
{ isArchived: parsedData.data.isArchived },
currentUser,
)
} catch (error) {
if (error instanceof NotFoundError) {
throw notFound()
}

throw error
}

return json<ActionData>({})
}

async function actionBan({
fosterFamilyId,
currentUser,
request,
}: Pick<ActionFunctionArgs, "request"> & {
formData,
}: {
fosterFamilyId: FosterFamily["id"]
currentUser: { id: string }
formData: FormData
}) {
const formData = BanActionFormData.safeParse(await request.formData())
if (!formData.success) {
const parsedData = BanActionFormData.safeParse(formData)
if (!parsedData.success) {
throw badRequest()
}

try {
await db.fosterFamily.update(
fosterFamilyId,
{ isBanned: formData.data.isBanned },
{ isBanned: parsedData.data.isBanned },
currentUser,
)
} catch (error) {
Expand Down Expand Up @@ -242,6 +301,11 @@ export default function Route() {
{fosterFamily.displayName} est actuellement banni.
</BlockHelper>
) : null}
{fosterFamily.isArchived ? (
<BlockHelper variant="neutral" icon="icon-ban-solid">
{fosterFamily.displayName} est actuellement archivé.
</BlockHelper>
) : null}
<HeaderCard />

<section className="grid grid-cols-1 gap-1 md:hidden">
Expand Down Expand Up @@ -426,6 +490,7 @@ function ActionsCard() {
<Card.Content>
<div className="flex flex-col gap-1">
<ActionBan />
<ActionArchive />
<ActionDelete />
</div>
</Card.Content>
Expand Down Expand Up @@ -475,6 +540,8 @@ function ActionBan() {
<Dialog.CloseAction>Annuler</Dialog.CloseAction>

<fetcher.Form method="POST" className="flex">
<input type="hidden" name="action" value="BAN" />

{!fosterFamily.isBanned ? (
<input
type="hidden"
Expand All @@ -493,6 +560,68 @@ function ActionBan() {
)
}

function ActionArchive() {
const { fosterFamily } = useLoaderData<typeof loader>()
const fetcher = useFetcher<typeof action>()
const [isDialogOpened, setIsDialogOpened] = useState(false)

const done = fetcher.state === "idle" && fetcher.data != null
useEffect(() => {
if (done) {
setIsDialogOpened(false)
}
}, [done])

return (
<Dialog open={isDialogOpened} onOpenChange={setIsDialogOpened}>
<Dialog.Trigger asChild>
<Action variant="secondary" color="gray">
<Action.Icon href="icon-ban-solid" />
{fosterFamily.isArchived ? "Désarchiver" : "Archiver"}
</Action>
</Dialog.Trigger>

<Dialog.Content variant="warning">
<Dialog.Header>
{fosterFamily.isArchived ? "Désarchiver" : "Archiver"}{" "}
{fosterFamily.displayName}
</Dialog.Header>

<Dialog.Message>
Êtes-vous sûr de vouloir{" "}
{fosterFamily.isArchived ? "désarchiver" : "archiver"}{" "}
<strong className="text-body-emphasis">
{fosterFamily.displayName}
</strong>
{" "}?
</Dialog.Message>

<ErrorsInlineHelper errors={fetcher.data?.errors} />

<Dialog.Actions>
<Dialog.CloseAction>Annuler</Dialog.CloseAction>

<fetcher.Form method="POST" className="flex">
<input type="hidden" name="action" value="ARCHIVE" />

{!fosterFamily.isArchived ? (
<input
type="hidden"
name={ArchiveActionFormData.keys.isArchived}
value="on"
/>
) : null}

<Dialog.ConfirmAction type="submit">
Oui, {fosterFamily.isArchived ? "désarchiver" : "archiver"}
</Dialog.ConfirmAction>
</fetcher.Form>
</Dialog.Actions>
</Dialog.Content>
</Dialog>
)
}

function ActionDelete() {
const { fosterFamily, fosterAnimalCount } = useLoaderData<typeof loader>()
const canDelete = fosterAnimalCount === 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
email: true,
garden: true,
housing: true,
isArchived: true,
isBanned: true,
phone: true,
speciesAlreadyPresent: true,
Expand Down
10 changes: 10 additions & 0 deletions apps/admin/src/routes/_layout.foster-families._index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
displayName: true,
fosterAnimals: { select: { avatar: true, name: true, id: true } },
id: true,
isArchived: true,
isBanned: true,
zipCode: true,
},
Expand Down Expand Up @@ -225,6 +226,15 @@ function FosterFamilyItem({
<span className="text-gray-500">{getShortLocation(fosterFamily)}</span>
</span>

{fosterFamily.isArchived ? (
<Chip
variant="primary"
color="grey"
icon="icon-ban-solid"
title="Archivé"
/>
) : null}

{fosterFamily.isBanned ? (
<Chip
variant="primary"
Expand Down
2 changes: 1 addition & 1 deletion apps/admin/src/routes/resources.foster-family/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
fosterFamilies: await db.fosterFamily.fuzzySearch(
searchParams.displayName,
{
where: { isBanned: false },
where: { isBanned: false, isArchived: false },
select: {
availability: true,
city: true,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "FosterFamily" ADD COLUMN "isArchived" BOOLEAN NOT NULL DEFAULT false;
1 change: 1 addition & 0 deletions libs/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ model FosterFamily {
email String @unique @db.VarChar(255)
garden FosterFamilyGarden @default(UNKNOWN)
housing FosterFamilyHousing @default(UNKNOWN)
isArchived Boolean @default(false)
isBanned Boolean @default(false)
phone String @db.VarChar(255)
speciesAlreadyPresent Species[] @default([])
Expand Down
Loading