refactor: rename recipients route to people, update all frontend references

This commit is contained in:
2026-06-16 11:26:21 +02:00
parent d67f31cf54
commit ecc3cf1b55
37 changed files with 553 additions and 194 deletions
+6 -6
View File
@@ -1,7 +1,7 @@
import { getI18n } from "@/i18n/server"
import { AssetService } from "@/services/asset.service"
import { ItemService } from "@/services/item.service"
import { RecipientService } from "@/services/recipient.service"
import { PersonService } from "@/services/person.service"
import Card from "./_components/card"
@@ -10,7 +10,7 @@ export default async function Home() {
const copy = dictionary.dashboardHome
const totalItems = await ItemService.findAllItemsCount()
const totalAssets = await AssetService.findAllAssetsCount()
const totalRecipients = await RecipientService.findAllRecipientsCount()
const totalPeople = await PersonService.findAllPeopleCount()
return (
<div className="container mx-auto p-4">
@@ -65,10 +65,10 @@ export default async function Home() {
}
/>
<Card
title={copy.cards.recipients.title}
total={totalRecipients}
countLabel={copy.cards.recipients.countLabel}
href="/recipients"
title={copy.cards.people.title}
total={totalPeople}
countLabel={copy.cards.people.countLabel}
href="/people"
icon={
<svg
xmlns="http://www.w3.org/2000/svg"
@@ -3,7 +3,7 @@ import type { UpdateAssignmentFormType } from "@/schemas/assignment.schema"
import { AssetService } from "@/services/asset.service"
import { AssignmentService } from "@/services/assignment.service"
import { ItemService } from "@/services/item.service"
import { RecipientService } from "@/services/recipient.service"
import { PersonService } from "@/services/person.service"
import type { Item } from "@/types"
import AssignmentForm from "../../_components/edit.assignment.form"
@@ -14,7 +14,7 @@ export default async function EditAssignmentPage({
}) {
const { assignmentId } = await params
const assignment = await AssignmentService.findById(assignmentId)
const recipients = await RecipientService.findAll()
const people = await PersonService.findAll()
const items = await ItemService.findAllWithStock()
const assets = await AssetService.findAll()
const { dictionary } = await getI18n()
@@ -37,7 +37,7 @@ export default async function EditAssignmentPage({
<h1 className="text-2xl font-bold">{copy.edit.title}</h1>
</div>
<AssignmentForm
recipients={recipients}
recipients={people}
items={items}
assets={assets}
initialData={assignment as UpdateAssignmentFormType}
@@ -15,13 +15,13 @@ import {
buildUpdateAssignmentSchema,
type UpdateAssignmentFormType,
} from "@/schemas/assignment.schema"
import type { Asset, Item, Recipient } from "@/types"
import type { Asset, Item, Person } from "@/types"
type AssignmentFormCopy = Dictionary["inventory"]["assignments"]["form"]
type AssignmentSchemaCopy = Dictionary["inventory"]["assignments"]["schema"]
interface Props {
recipients: Recipient[]
recipients: Person[]
items: Item[]
assets: Asset[]
initialData: UpdateAssignmentFormType
@@ -15,13 +15,13 @@ import {
buildCreateAssignmentSchema,
type CreateAssignmentFormType,
} from "@/schemas/assignment.schema"
import type { Asset, Item, Recipient } from "@/types"
import type { Asset, Item, Person } from "@/types"
type AssignmentFormCopy = Dictionary["inventory"]["assignments"]["form"]
type AssignmentSchemaCopy = Dictionary["inventory"]["assignments"]["schema"]
interface Props {
recipients: Recipient[]
recipients: Person[]
items: Item[]
assets: Asset[]
formCopy: AssignmentFormCopy
+3 -3
View File
@@ -1,12 +1,12 @@
import { getI18n } from "@/i18n/server"
import { AssetService } from "@/services/asset.service"
import { ItemService } from "@/services/item.service"
import { RecipientService } from "@/services/recipient.service"
import { PersonService } from "@/services/person.service"
import AssignmentForm from "../_components/new.assignment.form"
export default async function NewAssignmentPage() {
const recipients = await RecipientService.findAll()
const people = await PersonService.findAll()
const items = await ItemService.findAllWithStock()
const assets = await AssetService.findAllAvailable()
const { dictionary } = await getI18n()
@@ -18,7 +18,7 @@ export default async function NewAssignmentPage() {
<h1 className="text-2xl font-bold">{copy.new.title}</h1>
</div>
<AssignmentForm
recipients={recipients}
recipients={people}
items={items}
assets={assets}
formCopy={copy.form}
+1 -1
View File
@@ -63,7 +63,7 @@ export default async function AssignmentsPage(props: {
<tr key={assignment.id} className="border-b">
<td className="p-4">
<Link
href={`/recipients/${assignment?.recipient?.id}`}
href={`/people/${assignment?.recipient?.id}`}
className="hover:underline"
>
{assignment?.recipient?.firstName}{" "}
@@ -3,7 +3,7 @@
import { getI18n } from "@/i18n/server"
import { AssetService } from "@/services/asset.service"
import { ItemService } from "@/services/item.service"
import { RecipientService } from "@/services/recipient.service"
import { PersonService } from "@/services/person.service"
import type { AssetWithAssignment } from "@/types"
import EditAssetForm from "../../_components/edit.asset.form"
@@ -15,7 +15,7 @@ export default async function EditAssetPage({
}) {
const { assetId } = await params
const items = await ItemService.findAll()
const recipients = await RecipientService.findAll()
const people = await PersonService.findAll()
const asset = await AssetService.findById(assetId)
const { dictionary } = await getI18n()
const copy = dictionary.inventory.assets
@@ -31,7 +31,7 @@ export default async function EditAssetPage({
</div>
<EditAssetForm
items={items}
recipients={recipients}
recipients={people}
asset={asset as unknown as AssetWithAssignment}
formCopy={copy.form}
schemaCopy={copy.schema}
@@ -18,7 +18,7 @@ import {
import type {
AssetWithAssignment,
Item,
Recipient,
Person,
UpdateAssetStatus,
} from "@/types"
@@ -31,7 +31,7 @@ import type {
interface EditAssetFormProps {
asset: AssetWithAssignment
items: Item[]
recipients: Recipient[]
recipients: Person[]
formCopy: AssetFormCopy
schemaCopy: AssetSchemaCopy
statusCopy: AssetStatusCopy
@@ -15,7 +15,7 @@ import {
buildCreateAssetSchema,
type CreateAssetFormType,
} from "@/schemas/asset.schema"
import type { ItemWithoutStock, Recipient } from "@/types"
import type { ItemWithoutStock, Person } from "@/types"
import type {
AssetFormCopy,
@@ -25,7 +25,7 @@ import type {
interface NewAssetFormProps {
items: ItemWithoutStock[]
recipients: Recipient[]
recipients: Person[]
formCopy: AssetFormCopy
schemaCopy: AssetSchemaCopy
statusCopy: AssetStatusCopy
@@ -2,13 +2,13 @@
import { getI18n } from "@/i18n/server"
import { ItemService } from "@/services/item.service"
import { RecipientService } from "@/services/recipient.service"
import { PersonService } from "@/services/person.service"
import NewAssetForm from "../_components/new.asset.form"
export default async function NewAssetPage() {
const items = await ItemService.findAllAssignable()
const recipients = await RecipientService.findAll()
const people = await PersonService.findAll()
const { dictionary } = await getI18n()
const copy = dictionary.inventory.assets
@@ -19,7 +19,7 @@ export default async function NewAssetPage() {
</div>
<NewAssetForm
items={items}
recipients={recipients}
recipients={people}
formCopy={copy.form}
schemaCopy={copy.schema}
statusCopy={copy.status}
@@ -1,19 +1,19 @@
import { getI18n } from "@/i18n/server"
import { RecipientService } from "@/services/recipient.service"
import { PersonService } from "@/services/person.service"
import RecipientForm from "../../_components/recipient.form"
import PersonForm from "../../_components/person.form"
export default async function RecipientEditPage({
export default async function PersonEditPage({
params,
}: {
params: Promise<{ recipientId: string }>
params: Promise<{ personId: string }>
}) {
const { recipientId } = await params
const { personId } = await params
const { dictionary } = await getI18n()
const copy = dictionary.inventory.recipients
const recipient = await RecipientService.findById(recipientId)
const copy = dictionary.inventory.people
const person = await PersonService.findById(personId)
if (!recipient) {
if (!person) {
return <div>{copy.edit.notFound}</div>
}
@@ -22,8 +22,8 @@ export default async function RecipientEditPage({
<div className="flex items-center justify-between gap-4">
<h1 className="text-2xl font-bold">{copy.edit.title}</h1>
</div>
<RecipientForm
initialData={recipient}
<PersonForm
initialData={person}
mode="edit"
formCopy={copy.form}
schemaCopy={copy.schema}
@@ -1,23 +1,23 @@
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { getI18n } from "@/i18n/server"
import { AssignmentService } from "@/services/assignment.service"
import { RecipientService } from "@/services/recipient.service"
import { PersonService } from "@/services/person.service"
import { formatRecipientDepartment } from "../_components/recipient.copy"
import { formatPersonDepartment } from "../_components/person.copy"
export default async function RecipientInfoPage({
export default async function PersonInfoPage({
params,
}: {
params: Promise<{ recipientId: string }>
params: Promise<{ personId: string }>
}) {
const { recipientId } = await params
const { personId } = await params
const { dictionary } = await getI18n()
const copy = dictionary.inventory.recipients
const copy = dictionary.inventory.people
const assignmentCopy = dictionary.inventory.assignments
const recipient = await RecipientService.findById(recipientId)
const assignments = await AssignmentService.findAllByRecipient(recipientId)
const person = await PersonService.findById(personId)
const assignments = await AssignmentService.findAllByPerson(personId)
if (!recipient) {
if (!person) {
return <div>{copy.detail.notFound}</div>
}
@@ -25,33 +25,25 @@ export default async function RecipientInfoPage({
<div className="grid gap-6">
<Card className="rounded-sm shadow-none">
<CardHeader>
<CardTitle>
{`${recipient.firstName} ${recipient.lastName}`}
</CardTitle>
<CardTitle>{`${person.firstName} ${person.lastName}`}</CardTitle>
</CardHeader>
<CardContent>
<div className="grid grid-cols-2 gap-x-8 gap-y-2 text-sm">
<div className="flex justify-between">
<span className="text-gray-600">
{copy.detail.labels.username}
</span>
<span>{recipient.username}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-600">{copy.detail.labels.email}</span>
<span>{recipient.email}</span>
<span>{person.email}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-600">{copy.detail.labels.phone}</span>
<span>{recipient.phone}</span>
<span>{person.phone}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-600">
{copy.detail.labels.department}
</span>
<span>
{formatRecipientDepartment(
recipient.department,
{formatPersonDepartment(
person.department,
copy.departments,
copy.fallback,
)}
@@ -0,0 +1,22 @@
import type { Dictionary } from "@/i18n/dictionaries"
export type PersonListCopy = Dictionary["inventory"]["people"]["list"]
export type PersonDetailCopy = Dictionary["inventory"]["people"]["detail"]
export type PersonFormCopy = Dictionary["inventory"]["people"]["form"]
export type PersonDepartmentCopy =
Dictionary["inventory"]["people"]["departments"]
export type PersonFallbackCopy = Dictionary["inventory"]["people"]["fallback"]
export function formatPersonDepartment(
department: string | null | undefined,
departmentCopy: PersonDepartmentCopy,
fallbackCopy: PersonFallbackCopy,
) {
if (!department) {
return fallbackCopy.unknownDepartment
}
return department in departmentCopy
? departmentCopy[department as keyof PersonDepartmentCopy]
: fallbackCopy.unknownDepartment
}
@@ -5,42 +5,39 @@ import { useRouter } from "next/navigation"
import { useMemo } from "react"
import { useForm } from "react-hook-form"
import { toast } from "sonner"
import {
createNewRecipient,
updateRecipient,
} from "@/actions/recipient.actions"
import { createNewPerson, updatePerson } from "@/actions/person.actions"
import {
SubmitButton,
type SubmitButtonCopy,
} from "@/components/forms/submitButton"
import { RECIPIENT_DEPARTMENTS } from "@/lib/constants"
import { PERSON_DEPARTMENTS } from "@/lib/constants"
import {
buildCreateRecipientSchema,
buildUpdateRecipientSchema,
type CreateRecipientFormType,
type RecipientSchemaCopy,
type UpdateRecipientFormType,
} from "@/schemas/recipient.schema"
import type { Recipient } from "@/types"
buildCreatePersonSchema,
buildUpdatePersonSchema,
type CreatePersonFormType,
type PersonSchemaCopy,
type UpdatePersonFormType,
} from "@/schemas/person.schema"
import type { Person } from "@/types"
import {
formatRecipientDepartment,
type RecipientDepartmentCopy,
type RecipientFallbackCopy,
type RecipientFormCopy,
} from "./recipient.copy"
formatPersonDepartment,
type PersonDepartmentCopy,
type PersonFallbackCopy,
type PersonFormCopy,
} from "./person.copy"
interface RecipientFormProps {
initialData?: Recipient
interface PersonFormProps {
initialData?: Person
mode?: "create" | "edit"
formCopy: RecipientFormCopy
schemaCopy: RecipientSchemaCopy
departmentCopy: RecipientDepartmentCopy
fallbackCopy: RecipientFallbackCopy
formCopy: PersonFormCopy
schemaCopy: PersonSchemaCopy
departmentCopy: PersonDepartmentCopy
fallbackCopy: PersonFallbackCopy
submitButtonCopy: SubmitButtonCopy
}
export default function RecipientForm({
export default function PersonForm({
initialData,
mode = "create",
formCopy,
@@ -48,13 +45,13 @@ export default function RecipientForm({
departmentCopy,
fallbackCopy,
submitButtonCopy,
}: RecipientFormProps) {
}: PersonFormProps) {
const router = useRouter()
const schema = useMemo(
() =>
mode === "create"
? buildCreateRecipientSchema(schemaCopy)
: buildUpdateRecipientSchema(schemaCopy),
? buildCreatePersonSchema(schemaCopy)
: buildUpdatePersonSchema(schemaCopy),
[mode, schemaCopy],
)
@@ -63,11 +60,10 @@ export default function RecipientForm({
handleSubmit,
setError,
formState: { errors, isSubmitting, isSubmitSuccessful },
} = useForm<CreateRecipientFormType>({
} = useForm<CreatePersonFormType>({
resolver: zodResolver(schema),
defaultValues: {
id: initialData?.id || "",
username: initialData?.username || "",
firstName: initialData?.firstName || "",
lastName: initialData?.lastName || "",
department: initialData?.department || "OTHER",
@@ -76,16 +72,16 @@ export default function RecipientForm({
},
})
const onSubmit = async (formData: CreateRecipientFormType) => {
const onSubmit = async (formData: CreatePersonFormType) => {
const response =
mode === "create"
? await createNewRecipient(formData)
: await updateRecipient(formData as UpdateRecipientFormType)
? await createNewPerson(formData)
: await updatePerson(formData as UpdatePersonFormType)
if (response?.errors) {
Object.entries(response.errors).forEach(([fieldName, messages]) => {
messages.forEach((msg: string) => {
setError(fieldName as keyof CreateRecipientFormType, {
setError(fieldName as keyof CreatePersonFormType, {
type: "server",
message: msg,
})
@@ -97,28 +93,13 @@ export default function RecipientForm({
if (response?.success) {
toast.success(response.message)
router.push("/recipients")
router.push("/people")
}
}
return (
<form className="flex flex-col gap-4" onSubmit={handleSubmit(onSubmit)}>
<input type="hidden" {...register("id")} />
<div>
<label htmlFor="username" className="mb-2 block text-lg">
{formCopy.usernameLabel}
</label>
<input
type="text"
id="username"
placeholder={formCopy.usernamePlaceholder}
{...register("username")}
className={`w-full rounded-lg border px-4 py-2`}
/>
{errors?.username && (
<p className="text-error">{errors.username.message}</p>
)}
</div>
<div>
<label htmlFor="firstName" className="mb-2 block text-lg">
{formCopy.firstNameLabel}
@@ -159,13 +140,9 @@ export default function RecipientForm({
className="w-full rounded-lg border px-4 py-2"
>
<option value="">{formCopy.departmentPlaceholder}</option>
{Object.keys(RECIPIENT_DEPARTMENTS).map((department) => (
{Object.keys(PERSON_DEPARTMENTS).map((department) => (
<option key={department} value={department}>
{formatRecipientDepartment(
department,
departmentCopy,
fallbackCopy,
)}
{formatPersonDepartment(department, departmentCopy, fallbackCopy)}
</option>
))}
</select>
@@ -1,17 +1,17 @@
import { getI18n } from "@/i18n/server"
import RecipientForm from "../_components/recipient.form"
import PersonForm from "../_components/person.form"
export default async function NewRecipientPage() {
export default async function NewPersonPage() {
const { dictionary } = await getI18n()
const copy = dictionary.inventory.recipients
const copy = dictionary.inventory.people
return (
<div className="flex flex-col gap-4">
<div className="flex items-center justify-between gap-4">
<h1 className="text-2xl font-bold">{copy.new.title}</h1>
</div>
<RecipientForm
<PersonForm
mode="create"
formCopy={copy.form}
schemaCopy={copy.schema}
@@ -4,13 +4,13 @@ import Link from "next/link"
import PageHeader from "@/components/common/pageheader"
import PaginationButtons from "@/components/common/pagination"
import { Button } from "@/components/ui/button"
import type { Recipient } from "@/generated/prisma/client"
import type { Person } from "@/generated/prisma/client"
import { getI18n } from "@/i18n/server"
import { RecipientService } from "@/services/recipient.service"
import { PersonService } from "@/services/person.service"
import { formatRecipientDepartment } from "./_components/recipient.copy"
import { formatPersonDepartment } from "./_components/person.copy"
export default async function RecipientsPage(props: {
export default async function PeoplePage(props: {
searchParams?: Promise<{
page?: string
search?: string
@@ -19,33 +19,29 @@ export default async function RecipientsPage(props: {
const searchParams = await props.searchParams
const currentPage = searchParams?.page ? parseInt(searchParams.page, 10) : 1
const search = searchParams?.search || ""
const { data: recipients, totalPages } =
await RecipientService.findAllPaginated({
page: currentPage,
pageSize: 10,
search,
})
const { data: people, totalPages } = await PersonService.findAllPaginated({
page: currentPage,
pageSize: 10,
search,
})
const { dictionary } = await getI18n()
const copy = dictionary.inventory.recipients
const copy = dictionary.inventory.people
return (
<div className="flex flex-col gap-4">
<PageHeader
title={copy.list.title}
link="/recipients/new"
link="/people/new"
addLabel={copy.list.addLabel}
data={recipients}
data={people}
search={search}
/>
{recipients.length === 0 && <div>{copy.list.empty}</div>}
{recipients.length > 0 && (
{people.length === 0 && <div>{copy.list.empty}</div>}
{people.length > 0 && (
<div className="overflow-x-auto">
<table className="text-muted-foreground w-full text-left text-sm">
<thead className="border-b">
<tr>
<th scope="col" className="p-4">
{copy.list.columns.username}
</th>
<th scope="col" className="p-4">
{copy.list.columns.name}
</th>
@@ -64,23 +60,22 @@ export default async function RecipientsPage(props: {
</tr>
</thead>
<tbody>
{recipients.map((recipient: Recipient) => (
<tr key={recipient.id} className="border-b">
<td className="p-4">{recipient.username}</td>
{people.map((person: Person) => (
<tr key={person.id} className="border-b">
<td className="p-4">
{`${recipient.firstName} ${recipient.lastName}`}
{`${person.firstName} ${person.lastName}`}
</td>
<td className="p-4">{recipient.email}</td>
<td className="p-4">{recipient.phone}</td>
<td className="p-4">{person.email}</td>
<td className="p-4">{person.phone}</td>
<td className="p-4">
{formatRecipientDepartment(
recipient.department,
{formatPersonDepartment(
person.department,
copy.departments,
copy.fallback,
)}
</td>
<td className="flex items-center gap-2 p-4">
<Link href={`/recipients/${recipient.id}`} passHref>
<Link href={`/people/${person.id}`} passHref>
<Button
variant="outline"
size="icon"
@@ -89,7 +84,7 @@ export default async function RecipientsPage(props: {
<Eye />
</Button>
</Link>
<Link href={`/recipients/${recipient.id}/edit`} passHref>
<Link href={`/people/${person.id}/edit`} passHref>
<Button
className="btn btn-primary"
variant="outline"
@@ -105,7 +100,7 @@ export default async function RecipientsPage(props: {
</tbody>
<tfoot className="border-t">
<tr>
<td colSpan={6} className="p-4 text-center text-sm">
<td colSpan={5} className="p-4 text-center text-sm">
<PaginationButtons totalPages={totalPages} />
</td>
</tr>
@@ -1,24 +0,0 @@
import type { Dictionary } from "@/i18n/dictionaries"
export type RecipientListCopy = Dictionary["inventory"]["recipients"]["list"]
export type RecipientDetailCopy =
Dictionary["inventory"]["recipients"]["detail"]
export type RecipientFormCopy = Dictionary["inventory"]["recipients"]["form"]
export type RecipientDepartmentCopy =
Dictionary["inventory"]["recipients"]["departments"]
export type RecipientFallbackCopy =
Dictionary["inventory"]["recipients"]["fallback"]
export function formatRecipientDepartment(
department: string | null | undefined,
departmentCopy: RecipientDepartmentCopy,
fallbackCopy: RecipientFallbackCopy,
) {
if (!department) {
return fallbackCopy.unknownDepartment
}
return department in departmentCopy
? departmentCopy[department as keyof RecipientDepartmentCopy]
: fallbackCopy.unknownDepartment
}