Skip to content
Merged
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
8 changes: 8 additions & 0 deletions labman/src/app/(main)/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
16 changes: 8 additions & 8 deletions labman/src/components/core/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export default function Card({ loan, user, setSelectedLoanId, setSideView }: Car
}

return(
<div className="bg-brand-950 border-white border-[1px] rounded-[18px] ">
<div className="bg-brand-950 border-white border-[1px] rounded-[18px] max-w-[500px] ">
<div className="border-b-white border-b-[1px] flex gap-2 ">
<h1 className="text-3xl font-bold pl-3 pt-2.5 text-nowrap">{name}</h1>
{loan && <span className={"mt-3 text-3xl"}>|</span>}
Expand All @@ -50,20 +50,20 @@ export default function Card({ loan, user, setSelectedLoanId, setSideView }: Car

{loan && <div className="grid grid-cols-2 grid-rows-2 gap-4">
<div className="pl-3 pt-2.5 pb-2.5 w-fit">
<h1 className="text-2xl text-gray-300 font-bold">Equipment: </h1>
<h1 className="card-attributes-value">Equipment: </h1>
<p className="text-2xl">{loan.item.equipment.name}</p>
</div>

<div></div>

<div className="pl-3 pt-2.5 pb-2.5 w-fit">
<div className="grid grid-cols-2 grid-rows-3 gap-2">
<h1 className="text-2xl text-gray-300 font-bold">Borrower: </h1>
<h1 className="text-2xl ml-10">{loan.borrower.name}</h1>
<h1 className="text-2xl text-gray-300 font-bold">Start: </h1>
<h1 className="text-2xl ml-10">{start}</h1>
<h1 className="text-2xl text-gray-300 font-bold">End: </h1>
<h1 className="text-2xl ml-10">{last}</h1>
<h1 className="card-attributes-value">Borrower: </h1>
<h1 className="card-attributes" title={loan.borrower.name}>{loan.borrower.name}</h1>
<h1 className="card-attributes-value">Start: </h1>
<h1 className="card-attributes">{start}</h1>
<h1 className="card-attributes-value">End: </h1>
<h1 className="card-attributes">{last}</h1>
</div>
</div>
</div>}
Expand Down
2 changes: 1 addition & 1 deletion labman/src/components/core/CardList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export default function CardList({ loansProp = [], usersProp = []}: CardListProp
}

return (
<div className={"ml-5 mt-5"}>
<div className={"ml-5 mt-5 mr-5"}>
{ sideView == "loanEdit" && selectedLoanId && <EditLoan
loan={loans.find(loan => loan.id === selectedLoanId)!}
setLoans={setLoans}
Expand Down
24 changes: 21 additions & 3 deletions labman/src/components/core/SideView/ItemList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<number | undefined>;

if (props.variant === "selectable") {
if (props.variant === "selectableEdit") {
selectedUnitRef = useRef(props.selectedUnit?.id);

useEffect(() => {
Expand All @@ -42,7 +48,7 @@ export default function ItemList(props: Props) {
<div className="mt-2">
{props.equipmentData.items.map((unit, index) => (
<div key={unit.id} className="flex items-center justify-between bg-brand-200 rounded-md p-1 mb-3">
<h1 className={ props.variant === "selectable" && unit.id === selectedUnitRef.current ? "font-bold text-xl text-blue-600" : "font-bold text-xl text-black"}>{unit.id}</h1>
<h1 className={ props.variant === "selectableEdit" && unit.id === selectedUnitRef.current ? "font-bold text-xl text-blue-600" : "font-bold text-xl text-black"}>{unit.id}</h1>
{(() => {
switch (props.variant) {
case "editable":
Expand All @@ -58,6 +64,17 @@ export default function ItemList(props: Props) {

)
case "selectable":
return (
<>
{ unit.activeLoan && (unit.activeLoan.status !== "Returned") && <h1 className="text-black font-bold">Borrowed</h1>}
{ (unit.activeLoan == null || unit.activeLoan.status === "Returned") && <button
className="bg-white h-8 w-8 border-black border-1 rounded-full flex items-center justify-center"
onClick={() => props.setSelectedUnit(unit)}>
<div className={props.selectedUnit?.id == unit.id ? "bg-blue-600 h-4 w-4 rounded-full" : ""}></div>
</button>}
</>
)
case "selectableEdit":
return (
<>
{ unit.activeLoan && (unit.activeLoan.status !== "Returned" && unit.id !== selectedUnitRef.current) && <h1 className="text-black font-bold">Borrowed</h1>}
Expand All @@ -67,6 +84,7 @@ export default function ItemList(props: Props) {
<div className={props.selectedUnit?.id == unit.id ? "bg-blue-600 h-4 w-4 rounded-full" : ""}></div>
</button>}
</>

)
}
})()}
Expand Down
8 changes: 6 additions & 2 deletions labman/src/components/inventory/LoanView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion labman/src/components/loans/EditLoan.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export default function EditLoan({loan, setLoans}: EditLoanProps) {

return(
<>
<SideView title={"Edit loan"} equipmentData={loan.item.equipment} itemList={<ItemList equipmentData={loan.item.equipment} variant={"selectable"} selectedUnit={selectedUnit} setSelectedUnit={setSelectedUnit} />}>
<SideView title={"Edit loan"} equipmentData={loan.item.equipment} itemList={<ItemList equipmentData={loan.item.equipment} variant={"selectableEdit"} selectedUnit={selectedUnit} setSelectedUnit={setSelectedUnit} />}>
<>
<div className="mt-7 mb-10">
<button form="loanDataForm" type="submit" className={ (JSON.stringify(formData) === JSON.stringify(initialFormData) && selectedUnit.id === loan.item.id) ? "bg-blue-600 mr-2 button-deactive" : "bg-blue-600 button mr-2"}>Save changes</button>
Expand Down
34 changes: 17 additions & 17 deletions labman/src/lib/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> = | { type: "success"; data: T} | { type: "confirm"; message: string} | { type: "error"; message: string}
Expand Down Expand Up @@ -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"}
}
Expand All @@ -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<ActionResult<Loan>> {
export async function updateLoan (loanId: number, start : Date, end : Date, borrowerName : string, borrowerId : number, unitId : number, phone? : string | null, email? : string | null) : Promise<ActionResult<ExtendedLoan>> {
if (await getUser() === null) {return {type:"error", message: "Could not find a valid user"}}

// Check if the loan exists
Expand Down Expand Up @@ -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<ActionResult<Loan>> {
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: {
Expand All @@ -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() {
Expand Down
Loading