From 6f9aeebcc98259769eaf7e56810b32b607bc8a45 Mon Sep 17 00:00:00 2001 From: Ola Bekkevold Date: Fri, 13 Mar 2026 16:51:29 +0100 Subject: [PATCH 1/3] fix: loan status updates correctly in the UI Refs: #62 --- .../src/components/core/SideView/ItemList.tsx | 24 ++++++++++++++++--- labman/src/components/loans/EditLoan.tsx | 2 +- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/labman/src/components/core/SideView/ItemList.tsx b/labman/src/components/core/SideView/ItemList.tsx index b735576..acad258 100644 --- a/labman/src/components/core/SideView/ItemList.tsx +++ b/labman/src/components/core/SideView/ItemList.tsx @@ -12,20 +12,26 @@ type SelectableProps = BaseProps & { setSelectedUnit: (unit: Unit) => void; } +type SelectableEditProps = BaseProps & { + variant: "selectableEdit"; + selectedUnit: Unit | undefined; + setSelectedUnit: (unit: Unit) => void; +} + type editableProps = BaseProps & { variant: "editable"; handleAddUnit: (name: string) => void; handleDeleteUnit: (id: number) => void; } - type Props = SelectableProps | editableProps; + type Props = SelectableProps | editableProps | SelectableEditProps; export default function ItemList(props: Props) { // The initially selected unit has to persist between renders but uses to useEffect to update when the loan changes let selectedUnitRef : React.RefObject; - if (props.variant === "selectable") { + if (props.variant === "selectableEdit") { selectedUnitRef = useRef(props.selectedUnit?.id); useEffect(() => { @@ -42,7 +48,7 @@ export default function ItemList(props: Props) {
{props.equipmentData.items.map((unit, index) => (
-

{unit.id}

+

{unit.id}

{(() => { switch (props.variant) { case "editable": @@ -58,6 +64,17 @@ export default function ItemList(props: Props) { ) case "selectable": + return ( + <> + { unit.activeLoan && (unit.activeLoan.status !== "Returned") &&

Borrowed

} + { (unit.activeLoan == null || unit.activeLoan.status === "Returned") && } + + ) + case "selectableEdit": return ( <> { unit.activeLoan && (unit.activeLoan.status !== "Returned" && unit.id !== selectedUnitRef.current) &&

Borrowed

} @@ -67,6 +84,7 @@ export default function ItemList(props: Props) {
} + ) } })()} diff --git a/labman/src/components/loans/EditLoan.tsx b/labman/src/components/loans/EditLoan.tsx index 3236e11..8d902fb 100644 --- a/labman/src/components/loans/EditLoan.tsx +++ b/labman/src/components/loans/EditLoan.tsx @@ -96,7 +96,7 @@ export default function EditLoan({loan, setLoans}: EditLoanProps) { return( <> - }> + }> <>
From 463ebfb431572d6b13dbed20fb585d6ab729deb8 Mon Sep 17 00:00:00 2001 From: Ola Bekkevold Date: Mon, 16 Mar 2026 12:39:41 +0100 Subject: [PATCH 2/3] fix: prevent card attributes from causing line break force the values listed in the loan card to hide overflow to force them into a common design Refs: #61 --- labman/src/app/(main)/globals.css | 8 ++++++++ labman/src/components/core/Card.tsx | 16 ++++++++-------- labman/src/components/core/CardList.tsx | 2 +- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/labman/src/app/(main)/globals.css b/labman/src/app/(main)/globals.css index 2b45c59..6440177 100644 --- a/labman/src/app/(main)/globals.css +++ b/labman/src/app/(main)/globals.css @@ -101,4 +101,12 @@ input:invalid { .delete-button { @apply text-black font-bold rounded-full h-7 w-7 bg-red-600 +} + +.card-attributes { + @apply text-2xl ml-10 w-40 truncate +} + +.card-attributes-value { + @apply text-2xl text-gray-300 font-bold } \ No newline at end of file diff --git a/labman/src/components/core/Card.tsx b/labman/src/components/core/Card.tsx index 7d52d8b..9567717 100644 --- a/labman/src/components/core/Card.tsx +++ b/labman/src/components/core/Card.tsx @@ -33,7 +33,7 @@ export default function Card({ loan, user, setSelectedLoanId, setSideView }: Car } return( -
+

{name}

{loan && |} @@ -50,7 +50,7 @@ export default function Card({ loan, user, setSelectedLoanId, setSideView }: Car {loan &&
-

Equipment:

+

Equipment:

{loan.item.equipment.name}

@@ -58,12 +58,12 @@ export default function Card({ loan, user, setSelectedLoanId, setSideView }: Car
-

Borrower:

-

{loan.borrower.name}

-

Start:

-

{start}

-

End:

-

{last}

+

Borrower:

+

{loan.borrower.name}

+

Start:

+

{start}

+

End:

+

{last}

} diff --git a/labman/src/components/core/CardList.tsx b/labman/src/components/core/CardList.tsx index a0cce6e..6970801 100644 --- a/labman/src/components/core/CardList.tsx +++ b/labman/src/components/core/CardList.tsx @@ -112,7 +112,7 @@ export default function CardList({ loansProp = [], usersProp = []}: CardListProp } return ( -
+
{ sideView == "loanEdit" && selectedLoanId && loan.id === selectedLoanId)!} setLoans={setLoans} From 6d25c406628f93401bb4578ea9c67fa3a70d1392 Mon Sep 17 00:00:00 2001 From: Ola Bekkevold Date: Mon, 16 Mar 2026 15:56:18 +0100 Subject: [PATCH 3/3] fix: old user wont overwrite new user the add loan action will check if an existing user with the same phone/email exist and stop the user Refs: #60 --- labman/src/components/inventory/LoanView.tsx | 8 +++-- labman/src/lib/actions.ts | 34 ++++++++++---------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/labman/src/components/inventory/LoanView.tsx b/labman/src/components/inventory/LoanView.tsx index a0ed501..01e12b4 100644 --- a/labman/src/components/inventory/LoanView.tsx +++ b/labman/src/components/inventory/LoanView.tsx @@ -42,9 +42,13 @@ export default function LoanView({equipmentData, setAllEquipment, setSelectedEqu alert("Please fill in all required fields"); return; } - const newLoan = await addLoan(formData.borrower, formData.startDate, formData.endDate, selectedUnit.id, formData.borrowerPhone, formData.borrowerEmail); + const res = await addLoan(formData.borrower, formData.startDate, formData.endDate, selectedUnit.id, formData.borrowerPhone, formData.borrowerEmail); - if (!newLoan) return; + if (res.type !== "success") { + alert(res.message); + return; + } + const newLoan = res.data; const updatedEquipment = { ...equipmentData, diff --git a/labman/src/lib/actions.ts b/labman/src/lib/actions.ts index 5efb682..9744946 100644 --- a/labman/src/lib/actions.ts +++ b/labman/src/lib/actions.ts @@ -4,7 +4,8 @@ import {revalidatePath} from "next/cache"; import {deleteSession, validateSessionToken} from "@/auth/session" import {cookies} from "next/headers"; import {Borrower} from "@/generated/prisma"; -import {Loan} from "@/types/Loan"; +import {Loan as ExtendedLoan} from "@/types/Loan"; +import {Loan} from "@/generated/prisma"; import {redirect} from "next/navigation"; type ActionResult = | { type: "success"; data: T} | { type: "confirm"; message: string} | { type: "error"; message: string} @@ -153,19 +154,14 @@ export async function addBorrower(name: string, phone?: string | null, email?: s if (phone) { borrower = await prisma.borrower.findUnique({where:{phone: phone}}) - /* if (borrower && borrower.name !== borrowerName) { - if (window.confirm(`A borrower with the same phone number already exists with a different name (${borrower.name}). Click OK to assign this loan to ${borrowerName}. Click Cancel to assign it to ${borrower.name} instead.`)) { - borrower = null; - } - } */ - + if (borrower && borrower.name !== name) { + return {type: "error", message: `A borrower with the same phone number already exists (${borrower.name}). Please try again.`} + } } else if (email) { borrower = await prisma.borrower.findUnique({where:{email: email}}) - /*if (borrower && borrower.name !== borrowerName) { - if (window.confirm(`A borrower with the same email already exists with a different name (${borrower.name}). Click OK to assign this loan to ${borrowerName}. Click Cancel to assign it to ${borrower.name} instead.`)) { - borrower = null; - } - } */ + if (borrower && borrower.name !== name) { + return {type: "error", message: `A borrower with the same email already exists (${borrower.name}). Please try again.`} + } } else { return {type: "error", message: "No borrower phone/email provided"} } @@ -185,7 +181,7 @@ export async function addBorrower(name: string, phone?: string | null, email?: s return {type: "success", data: borrower}; } -export async function updateLoan (loanId: number, start : Date, end : Date, borrowerName : string, borrowerId : number, unitId : number, phone? : string | null, email? : string | null) : Promise> { +export async function updateLoan (loanId: number, start : Date, end : Date, borrowerName : string, borrowerId : number, unitId : number, phone? : string | null, email? : string | null) : Promise> { if (await getUser() === null) {return {type:"error", message: "Could not find a valid user"}} // Check if the loan exists @@ -246,14 +242,18 @@ export async function updateLoan (loanId: number, start : Date, end : Date, borr } -export async function addLoan (borrowerName : string, start : string, end : string, unitId : number, phone : string | null, email : string | null) { +export async function addLoan (borrowerName : string, start : string, end : string, unitId : number, phone : string | null, email : string | null) : Promise> { const dateStart = new Date(start); const dateEnd = new Date(end); const user = await getUser(); - if (!user) {alert("Could not find a valid user"); return} + if (!user) { + return {type: "error", message: "Could not find a valid user"} + } const res = await addBorrower(borrowerName, phone, email) - if (res.type !== "success") {return} + if (res.type !== "success") { + return {type: "error", message: res.message} + } const loan = await prisma.loan.create({ data: { @@ -271,7 +271,7 @@ export async function addLoan (borrowerName : string, start : string, end : stri data: {status: "Unavailable", activeLoanId: loan.id} }) revalidatePath("/"); - return loan; + return {type: "success", data: loan}; } export async function getUser() {