feat: borrower return book
also change some var names and headings to reflect when data is in borrower role and when data is in lender
This commit is contained in:
		
							parent
							
								
									5c328ab0a4
								
							
						
					
					
						commit
						3662189539
					
				@ -59,9 +59,9 @@ export default async function HomePage() {
 | 
				
			|||||||
      },
 | 
					      },
 | 
				
			||||||
    })) as PaginatedDocs<Repository>
 | 
					    })) as PaginatedDocs<Repository>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let userCheckouts: PaginatedDocs<Checkout> | null = null
 | 
					  let userBorrows: PaginatedDocs<Checkout> | null = null
 | 
				
			||||||
  if (user?.id)
 | 
					  if (user?.id)
 | 
				
			||||||
    userCheckouts = await payload.find({
 | 
					    userBorrows = await payload.find({
 | 
				
			||||||
      collection: 'checkouts',
 | 
					      collection: 'checkouts',
 | 
				
			||||||
      depth: 3,
 | 
					      depth: 3,
 | 
				
			||||||
      limit: 10,
 | 
					      limit: 10,
 | 
				
			||||||
@ -69,6 +69,8 @@ export default async function HomePage() {
 | 
				
			|||||||
        id: true,
 | 
					        id: true,
 | 
				
			||||||
        copy: true,
 | 
					        copy: true,
 | 
				
			||||||
        dateDue: true,
 | 
					        dateDue: true,
 | 
				
			||||||
 | 
					        ownerVerifiedReturnedDate: true,
 | 
				
			||||||
 | 
					        loaneeReturnedDate: true,
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      sort: 'dateDue',
 | 
					      sort: 'dateDue',
 | 
				
			||||||
      where: {
 | 
					      where: {
 | 
				
			||||||
@ -108,7 +110,7 @@ export default async function HomePage() {
 | 
				
			|||||||
            </TabsContent>
 | 
					            </TabsContent>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <TabsContent value="manage">
 | 
					            <TabsContent value="manage">
 | 
				
			||||||
              <Manage repos={userRepos} user={user} checkouts={userCheckouts} />
 | 
					              <Manage repos={userRepos} user={user} borrows={userBorrows} />
 | 
				
			||||||
            </TabsContent>
 | 
					            </TabsContent>
 | 
				
			||||||
          </Tabs>
 | 
					          </Tabs>
 | 
				
			||||||
        ) : (
 | 
					        ) : (
 | 
				
			||||||
 | 
				
			|||||||
@ -42,7 +42,7 @@ const Checkouts: CollectionConfig = {
 | 
				
			|||||||
      type: 'date',
 | 
					      type: 'date',
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      name: 'loanerReturnedDate',
 | 
					      name: 'loaneeReturnedDate',
 | 
				
			||||||
      type: 'date',
 | 
					      type: 'date',
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
@ -25,7 +25,7 @@ const UserFeed = async (props: Props) => {
 | 
				
			|||||||
  const payloadConfig = await config
 | 
					  const payloadConfig = await config
 | 
				
			||||||
  const payload = await getPayload({ config: payloadConfig })
 | 
					  const payload = await getPayload({ config: payloadConfig })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const holdRequests = (await payload.find({
 | 
					  const borrowRequests = (await payload.find({
 | 
				
			||||||
    collection: 'holdRequests',
 | 
					    collection: 'holdRequests',
 | 
				
			||||||
    limit: 10,
 | 
					    limit: 10,
 | 
				
			||||||
    depth: 3,
 | 
					    depth: 3,
 | 
				
			||||||
@ -137,7 +137,7 @@ const UserFeed = async (props: Props) => {
 | 
				
			|||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <section>
 | 
					    <section>
 | 
				
			||||||
      <div className="my-6">
 | 
					      <div className="my-6">
 | 
				
			||||||
        <h3 className="text-lg font-semibold text-foreground">Outbound Activity</h3>
 | 
					        <h3 className="text-lg font-semibold text-foreground">Loan Activity</h3>
 | 
				
			||||||
        <dl className="mt-5 grid grid-cols-1 gap-5 sm:grid-cols-3">
 | 
					        <dl className="mt-5 grid grid-cols-1 gap-5 sm:grid-cols-3">
 | 
				
			||||||
          {stats.map((s) => {
 | 
					          {stats.map((s) => {
 | 
				
			||||||
            return (
 | 
					            return (
 | 
				
			||||||
@ -182,11 +182,11 @@ const UserFeed = async (props: Props) => {
 | 
				
			|||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <div className="my-6">
 | 
					      <div className="my-6">
 | 
				
			||||||
        <h2 className="text-lg font-semibold text-foreground">Inbound Activity</h2>
 | 
					        <h2 className="text-lg font-semibold text-foreground">Borrow Activity</h2>
 | 
				
			||||||
        <div className="my-3">
 | 
					        <div className="my-3">
 | 
				
			||||||
          <h3 className="text-base font-semibold text-muted-foreground mb-4">Your Holds</h3>
 | 
					          <h3 className="text-base font-semibold text-muted-foreground mb-4">Your Holds</h3>
 | 
				
			||||||
          <ul className="grid grid-cols-1 gap-y-6 sm:grid-cols-3 md:grid-cols-4 last-child-adjustment">
 | 
					          <ul className="grid grid-cols-1 gap-y-6 sm:grid-cols-3 md:grid-cols-4 last-child-adjustment">
 | 
				
			||||||
            {holdRequests.docs?.map((h) => {
 | 
					            {borrowRequests.docs?.map((h) => {
 | 
				
			||||||
              const book = h.book as Book
 | 
					              const book = h.book as Book
 | 
				
			||||||
              const repository = h.repository as Repository
 | 
					              const repository = h.repository as Repository
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,14 +1,21 @@
 | 
				
			|||||||
 | 
					'use client'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Author, Book, Checkout, Copy, Repository } from '@/payload-types'
 | 
					import { Author, Book, Checkout, Copy, Repository } from '@/payload-types'
 | 
				
			||||||
 | 
					import { useGlobal } from '@/providers/GlobalProvider'
 | 
				
			||||||
 | 
					import { getUserBorrows } from '@/serverActions/GetUserBorrows'
 | 
				
			||||||
 | 
					import { loaneeReturnCheckout } from '@/serverActions/ReturnCheckout'
 | 
				
			||||||
import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/react'
 | 
					import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/react'
 | 
				
			||||||
import { EllipsisVerticalIcon } from '@heroicons/react/20/solid'
 | 
					import { EllipsisVerticalIcon } from '@heroicons/react/20/solid'
 | 
				
			||||||
import clsx from 'clsx'
 | 
					import clsx from 'clsx'
 | 
				
			||||||
import { Loader2Icon } from 'lucide-react'
 | 
					import { Loader2Icon } from 'lucide-react'
 | 
				
			||||||
import { PaginatedDocs, User } from 'payload'
 | 
					import { PaginatedDocs, User } from 'payload'
 | 
				
			||||||
import { useCallback, useState } from 'react'
 | 
					import { useCallback, useMemo, useState } from 'react'
 | 
				
			||||||
 | 
					import { toast } from 'sonner'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const statuses = {
 | 
					const statuses = {
 | 
				
			||||||
  'Passed Due': 'text-gray-200 bg-red-500 ring-red-700/10',
 | 
					  'Passed Due': 'text-gray-200 bg-red-500 ring-red-700/10',
 | 
				
			||||||
  'Due Soon': 'text-amber-800 bg-amber-50 ring-amber-600/20',
 | 
					  'Due Soon': 'text-amber-800 bg-amber-50 ring-amber-600/20',
 | 
				
			||||||
 | 
					  'Owner Action': 'text-emerald-800 bg-emerald-50 ring-emerald-600/20',
 | 
				
			||||||
  '': '',
 | 
					  '': '',
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -21,24 +28,50 @@ type Row = {
 | 
				
			|||||||
  status: 'Passed Due' | 'Due Soon' | ''
 | 
					  status: 'Passed Due' | 'Due Soon' | ''
 | 
				
			||||||
  dueDate: Date
 | 
					  dueDate: Date
 | 
				
			||||||
  href: string
 | 
					  href: string
 | 
				
			||||||
 | 
					  doesNeedOwnerVerify: boolean
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ListProps = { rows: Row[] }
 | 
					type ListProps = {
 | 
				
			||||||
const CheckedOutBooksList = (props: ListProps) => {
 | 
					  rows: Row[]
 | 
				
			||||||
 | 
					  onUpdate: () => Promise<void>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const BorrowedBooksList = (props: ListProps) => {
 | 
				
			||||||
  const { rows } = props
 | 
					  const { rows } = props
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const [returningBookId, setReturningBookId] = useState(0)
 | 
					  const [returningBookId, setReturningBookId] = useState(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const isReturningBook = useCallback((id: number) => id === returningBookId, [returningBookId])
 | 
					  const isReturningBook = useCallback((id: number) => id === returningBookId, [returningBookId])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const handleReturnClick = useCallback((id: number) => {
 | 
					  const handleReturnClick = useCallback(
 | 
				
			||||||
 | 
					    async (id: number) => {
 | 
				
			||||||
 | 
					      if (returningBookId) return
 | 
				
			||||||
      setReturningBookId(id)
 | 
					      setReturningBookId(id)
 | 
				
			||||||
  }, [])
 | 
					
 | 
				
			||||||
 | 
					      const updatedCheckout = await loaneeReturnCheckout({ checkoutId: id })
 | 
				
			||||||
 | 
					      if (!updatedCheckout) {
 | 
				
			||||||
 | 
					        setReturningBookId(0)
 | 
				
			||||||
 | 
					        toast('There was an issue returning your book')
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      await props.onUpdate()
 | 
				
			||||||
 | 
					      setReturningBookId(0)
 | 
				
			||||||
 | 
					      toast('Book was returned, awaiting owner verification.')
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    [returningBookId, setReturningBookId],
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <ul role="list" className="divide-y divide-gray-100">
 | 
					    <ul role="list" className="divide-y divide-gray-100">
 | 
				
			||||||
      {rows.map((r) => (
 | 
					      {rows.map((r) => (
 | 
				
			||||||
        <li key={r.id} className="flex items-center justify-between gap-x-6 py-5">
 | 
					        <li
 | 
				
			||||||
 | 
					          key={r.id}
 | 
				
			||||||
 | 
					          className={clsx(
 | 
				
			||||||
 | 
					            'flex relative items-center justify-between gap-x-6 py-5',
 | 
				
			||||||
 | 
					            isReturningBook(r.id) ? 'pointer-events-none opacity-30' : '',
 | 
				
			||||||
 | 
					            r.doesNeedOwnerVerify ? 'pointer-events-none opacity-30' : '',
 | 
				
			||||||
 | 
					          )}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
          <div className="min-w-0">
 | 
					          <div className="min-w-0">
 | 
				
			||||||
            <div className="flex items-start gap-x-3">
 | 
					            <div className="flex items-start gap-x-3">
 | 
				
			||||||
              <p className="text-sm/6 text-foreground">
 | 
					              <p className="text-sm/6 text-foreground">
 | 
				
			||||||
@ -58,7 +91,14 @@ const CheckedOutBooksList = (props: ListProps) => {
 | 
				
			|||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            <div className="mt-1 flex items-center gap-x-2 text-xs/5 text-gray-500">
 | 
					            <div className="mt-1 flex items-center gap-x-2 text-xs/5 text-gray-500">
 | 
				
			||||||
              <p className="whitespace-nowrap">
 | 
					              <p className="whitespace-nowrap">
 | 
				
			||||||
                Due on <time dateTime={r.dueDate.toString()}>{r.dueDate.toLocaleDateString()}</time>
 | 
					                {r.doesNeedOwnerVerify ? (
 | 
				
			||||||
 | 
					                  <span>Awaiting Owner Verification</span>
 | 
				
			||||||
 | 
					                ) : (
 | 
				
			||||||
 | 
					                  <span>
 | 
				
			||||||
 | 
					                    Due on{' '}
 | 
				
			||||||
 | 
					                    <time dateTime={r.dueDate.toString()}>{r.dueDate.toLocaleDateString()}</time>
 | 
				
			||||||
 | 
					                  </span>
 | 
				
			||||||
 | 
					                )}
 | 
				
			||||||
              </p>
 | 
					              </p>
 | 
				
			||||||
              <svg viewBox="0 0 2 2" className="size-0.5 fill-current">
 | 
					              <svg viewBox="0 0 2 2" className="size-0.5 fill-current">
 | 
				
			||||||
                <circle r={1} cx={1} cy={1} />
 | 
					                <circle r={1} cx={1} cy={1} />
 | 
				
			||||||
@ -87,21 +127,21 @@ const CheckedOutBooksList = (props: ListProps) => {
 | 
				
			|||||||
              >
 | 
					              >
 | 
				
			||||||
                <MenuItem>
 | 
					                <MenuItem>
 | 
				
			||||||
                  <button
 | 
					                  <button
 | 
				
			||||||
                    className="block cursor-pointer px-3 py-1 text-sm/6 text-gray-900 data-focus:bg-gray-50 data-focus:outline-hidden"
 | 
					                    className="block w-full text-left cursor-pointer px-3 py-1 text-sm/6 text-gray-900 data-focus:bg-gray-50 data-focus:outline-hidden"
 | 
				
			||||||
                    type="button"
 | 
					                    type="button"
 | 
				
			||||||
                    onClick={() => console.log('return')}
 | 
					                    onClick={() => handleReturnClick(r.id)}
 | 
				
			||||||
                  >
 | 
					                  >
 | 
				
			||||||
                    Return<span className="sr-only">, {r.title}</span>
 | 
					                    Return<span className="sr-only">, {r.title}</span>
 | 
				
			||||||
                  </button>
 | 
					                  </button>
 | 
				
			||||||
                </MenuItem>
 | 
					                </MenuItem>
 | 
				
			||||||
                <MenuItem>
 | 
					                {/*<MenuItem>
 | 
				
			||||||
                  <a
 | 
					                  <a
 | 
				
			||||||
                    href={`/repositories/${r.repositoryAbbreviation}`}
 | 
					                    href={`/repositories/${r.repositoryAbbreviation}`}
 | 
				
			||||||
                    className="block px-3 py-1 text-sm/6 text-gray-900 data-focus:bg-gray-50 data-focus:outline-hidden"
 | 
					                    className="block px-3 py-1 text-sm/6 text-gray-900 data-focus:bg-gray-50 data-focus:outline-hidden"
 | 
				
			||||||
                  >
 | 
					                  >
 | 
				
			||||||
                    Repository<span className="sr-only">, {r.repositoryAbbreviation}</span>
 | 
					                    Repository<span className="sr-only">, {r.repositoryAbbreviation}</span>
 | 
				
			||||||
                  </a>
 | 
					                  </a>
 | 
				
			||||||
                </MenuItem>
 | 
					                </MenuItem>*/}
 | 
				
			||||||
                <MenuItem>
 | 
					                <MenuItem>
 | 
				
			||||||
                  <a
 | 
					                  <a
 | 
				
			||||||
                    href={r.href}
 | 
					                    href={r.href}
 | 
				
			||||||
@ -119,13 +159,24 @@ const CheckedOutBooksList = (props: ListProps) => {
 | 
				
			|||||||
  )
 | 
					  )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Props = { initialCheckoutPage: PaginatedDocs<Checkout> | null }
 | 
					type Props = { initialBorrows: PaginatedDocs<Checkout> | null }
 | 
				
			||||||
const CheckedOutBooks = (props: Props) => {
 | 
					const BorrowedBooks = (props: Props) => {
 | 
				
			||||||
  const { initialCheckoutPage } = props
 | 
					  const { initialBorrows } = props
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const checkouts = initialCheckoutPage?.docs
 | 
					  const { user } = useGlobal()
 | 
				
			||||||
  const rows: Row[] =
 | 
					
 | 
				
			||||||
    checkouts?.map((c) => {
 | 
					  const [borrows, setBorrows] = useState<PaginatedDocs<Checkout> | null>(initialBorrows)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const onUpdate = useCallback(async () => {
 | 
				
			||||||
 | 
					    if (!user) return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const updatedUserBorrows = await getUserBorrows({ userId: user.id })
 | 
				
			||||||
 | 
					    setBorrows(updatedUserBorrows)
 | 
				
			||||||
 | 
					  }, [borrows, setBorrows])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const rows: Row[] = useMemo(
 | 
				
			||||||
 | 
					    () =>
 | 
				
			||||||
 | 
					      borrows?.docs?.map((c) => {
 | 
				
			||||||
        const copy = c.copy as Copy
 | 
					        const copy = c.copy as Copy
 | 
				
			||||||
        const book = copy.book as Book
 | 
					        const book = copy.book as Book
 | 
				
			||||||
        const authors = book.authors as Author[]
 | 
					        const authors = book.authors as Author[]
 | 
				
			||||||
@ -138,9 +189,11 @@ const CheckedOutBooks = (props: Props) => {
 | 
				
			|||||||
        const minutesUntilDue = Math.floor(secondsUntilDue / 60)
 | 
					        const minutesUntilDue = Math.floor(secondsUntilDue / 60)
 | 
				
			||||||
        const hoursUntilDue = Math.floor(minutesUntilDue / 60)
 | 
					        const hoursUntilDue = Math.floor(minutesUntilDue / 60)
 | 
				
			||||||
        const daysUntilDue = Math.floor(hoursUntilDue / 24)
 | 
					        const daysUntilDue = Math.floor(hoursUntilDue / 24)
 | 
				
			||||||
 | 
					        const doesNeedOwnerVerify = c.loaneeReturnedDate && !c.ownerVerifiedReturnedDate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let status = ''
 | 
					        let status = ''
 | 
				
			||||||
      if (daysUntilDue <= 0) status = 'Passed Due'
 | 
					        if (doesNeedOwnerVerify) status = 'Owner Action'
 | 
				
			||||||
 | 
					        else if (daysUntilDue <= 0) status = 'Passed Due'
 | 
				
			||||||
        else if (daysUntilDue <= 5) status = 'Due Soon'
 | 
					        else if (daysUntilDue <= 5) status = 'Due Soon'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
@ -148,24 +201,28 @@ const CheckedOutBooks = (props: Props) => {
 | 
				
			|||||||
          title: book.title || '',
 | 
					          title: book.title || '',
 | 
				
			||||||
          authors: authors.map((a) => a.lf) || ([] as string[]),
 | 
					          authors: authors.map((a) => a.lf) || ([] as string[]),
 | 
				
			||||||
          owners:
 | 
					          owners:
 | 
				
			||||||
          owners.map((o) => `${(o as User).firstName} ${(o as User).lastName}`) || ([] as string[]),
 | 
					            owners.map((o) => `${(o as User).firstName} ${(o as User).lastName}`) ||
 | 
				
			||||||
 | 
					            ([] as string[]),
 | 
				
			||||||
          repositoryAbbreviation: repository.abbreviation || '',
 | 
					          repositoryAbbreviation: repository.abbreviation || '',
 | 
				
			||||||
          status,
 | 
					          status,
 | 
				
			||||||
          dueDate: parsedDateDue,
 | 
					          dueDate: parsedDateDue,
 | 
				
			||||||
          href: `/books/${book.id}`,
 | 
					          href: `/books/${book.id}`,
 | 
				
			||||||
 | 
					          doesNeedOwnerVerify,
 | 
				
			||||||
        } as Row
 | 
					        } as Row
 | 
				
			||||||
    }) || []
 | 
					      }) || [],
 | 
				
			||||||
 | 
					    [borrows],
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!rows.length) return null
 | 
					  if (!rows.length) return null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <section className="py-6">
 | 
					    <section className="py-6">
 | 
				
			||||||
      <div className="mb-4 flex justify-between items-end">
 | 
					      <div className="mb-4 flex justify-between items-end">
 | 
				
			||||||
        <h3 className="px-4 text-lg font-semibold">Outbound Checked Out Books</h3>
 | 
					        <h3 className="px-4 text-lg font-semibold">Borrowed Books</h3>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <CheckedOutBooksList rows={rows} />
 | 
					      <BorrowedBooksList onUpdate={onUpdate} rows={rows} />
 | 
				
			||||||
    </section>
 | 
					    </section>
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default CheckedOutBooks
 | 
					export default BorrowedBooks
 | 
				
			||||||
@ -155,7 +155,7 @@ const HoldRequestNotifications = (props: Props) => {
 | 
				
			|||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <section className="py-6">
 | 
					    <section className="py-6">
 | 
				
			||||||
      <div className="mb-4 flex justify-between items-end">
 | 
					      <div className="mb-4 flex justify-between items-end">
 | 
				
			||||||
        <h3 className="px-4 text-lg font-semibold">Outbound Hold Requests</h3>
 | 
					        <h3 className="px-4 text-lg font-semibold">Incoming Hold Requests</h3>
 | 
				
			||||||
        {!!totalHoldNotifications && (
 | 
					        {!!totalHoldNotifications && (
 | 
				
			||||||
          <span className="font-bold">{totalHoldNotifications} Unaddressed</span>
 | 
					          <span className="font-bold">{totalHoldNotifications} Unaddressed</span>
 | 
				
			||||||
        )}
 | 
					        )}
 | 
				
			||||||
 | 
				
			|||||||
@ -4,15 +4,15 @@ import { Checkout, Repository, User } from '@/payload-types'
 | 
				
			|||||||
import { PaginatedDocs } from 'payload'
 | 
					import { PaginatedDocs } from 'payload'
 | 
				
			||||||
import RepoList from './RepoList'
 | 
					import RepoList from './RepoList'
 | 
				
			||||||
import HoldRequestNotifications from './HoldRequests'
 | 
					import HoldRequestNotifications from './HoldRequests'
 | 
				
			||||||
import CheckedOutBooks from './CheckedOutBooks'
 | 
					import BorrowedBooks from './BorrowedBooks'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Props = {
 | 
					type Props = {
 | 
				
			||||||
  repos: PaginatedDocs<Repository> | null
 | 
					  repos: PaginatedDocs<Repository> | null
 | 
				
			||||||
  checkouts: PaginatedDocs<Checkout> | null
 | 
					  borrows: PaginatedDocs<Checkout> | null
 | 
				
			||||||
  user: User | null
 | 
					  user: User | null
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
const Manage = (props: Props) => {
 | 
					const Manage = (props: Props) => {
 | 
				
			||||||
  const { repos, checkouts, user } = props
 | 
					  const { repos, borrows, user } = props
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <section>
 | 
					    <section>
 | 
				
			||||||
@ -23,7 +23,7 @@ const Manage = (props: Props) => {
 | 
				
			|||||||
      <div>{user && <HoldRequestNotifications repos={repos} user={user} />}</div>
 | 
					      <div>{user && <HoldRequestNotifications repos={repos} user={user} />}</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <div>
 | 
					      <div>
 | 
				
			||||||
        <CheckedOutBooks initialCheckoutPage={checkouts} />
 | 
					        <BorrowedBooks initialBorrows={borrows} />
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </section>
 | 
					    </section>
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
				
			|||||||
@ -350,7 +350,7 @@ export interface Checkout {
 | 
				
			|||||||
  isReturned?: boolean | null;
 | 
					  isReturned?: boolean | null;
 | 
				
			||||||
  dateDue?: string | null;
 | 
					  dateDue?: string | null;
 | 
				
			||||||
  ownerVerifiedReturnedDate?: string | null;
 | 
					  ownerVerifiedReturnedDate?: string | null;
 | 
				
			||||||
  loanerReturnedDate?: string | null;
 | 
					  loaneeReturnedDate?: string | null;
 | 
				
			||||||
  book?: {
 | 
					  book?: {
 | 
				
			||||||
    docs?: (number | Copy)[];
 | 
					    docs?: (number | Copy)[];
 | 
				
			||||||
    hasNextPage?: boolean;
 | 
					    hasNextPage?: boolean;
 | 
				
			||||||
@ -598,7 +598,7 @@ export interface CheckoutsSelect<T extends boolean = true> {
 | 
				
			|||||||
  isReturned?: T;
 | 
					  isReturned?: T;
 | 
				
			||||||
  dateDue?: T;
 | 
					  dateDue?: T;
 | 
				
			||||||
  ownerVerifiedReturnedDate?: T;
 | 
					  ownerVerifiedReturnedDate?: T;
 | 
				
			||||||
  loanerReturnedDate?: T;
 | 
					  loaneeReturnedDate?: T;
 | 
				
			||||||
  book?: T;
 | 
					  book?: T;
 | 
				
			||||||
  updatedAt?: T;
 | 
					  updatedAt?: T;
 | 
				
			||||||
  createdAt?: T;
 | 
					  createdAt?: T;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										53
									
								
								src/serverActions/GetUserBorrows.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/serverActions/GetUserBorrows.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					'use server'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { getPayload } from 'payload'
 | 
				
			||||||
 | 
					import config from '@/payload.config'
 | 
				
			||||||
 | 
					import type { PaginatedDocs } from "payload"
 | 
				
			||||||
 | 
					import { Checkout } from '@/payload-types'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Props = {
 | 
				
			||||||
 | 
					  userId: number
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					export const getUserBorrows = async (props: Props) => {
 | 
				
			||||||
 | 
					  const { userId } = props
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const payloadConfig = await config
 | 
				
			||||||
 | 
					  const payload = await getPayload({ config: payloadConfig })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let userBorrows: PaginatedDocs<Checkout> | null = null
 | 
				
			||||||
 | 
					  if (userId)
 | 
				
			||||||
 | 
					    userBorrows = await payload.find({
 | 
				
			||||||
 | 
					      collection: 'checkouts',
 | 
				
			||||||
 | 
					      depth: 3,
 | 
				
			||||||
 | 
					      limit: 10,
 | 
				
			||||||
 | 
					      select: {
 | 
				
			||||||
 | 
					        id: true,
 | 
				
			||||||
 | 
					        copy: true,
 | 
				
			||||||
 | 
					        dateDue: true,
 | 
				
			||||||
 | 
					        ownerVerifiedReturnedDate: true,
 | 
				
			||||||
 | 
					        loaneeReturnedDate: true,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      sort: 'dateDue',
 | 
				
			||||||
 | 
					      where: {
 | 
				
			||||||
 | 
					        and: [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            isReturned: {
 | 
				
			||||||
 | 
					              not_equals: true,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            'user.id': {
 | 
				
			||||||
 | 
					              equals: userId,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            ownerVerifiedReturnedDate: {
 | 
				
			||||||
 | 
					              equals: null,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    }) as PaginatedDocs<Checkout>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return userBorrows
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										49
									
								
								src/serverActions/ReturnCheckout.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/serverActions/ReturnCheckout.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					'use server'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { getPayload } from 'payload'
 | 
				
			||||||
 | 
					import config from '@/payload.config'
 | 
				
			||||||
 | 
					import { Checkout } from '@/payload-types'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Props = {
 | 
				
			||||||
 | 
					  checkoutId: number
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					export const loaneeReturnCheckout = async (props: Props): Promise<Checkout | null> => {
 | 
				
			||||||
 | 
					  const { checkoutId } = props
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const payloadConfig = await config
 | 
				
			||||||
 | 
					  const payload = await getPayload({ config: payloadConfig })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    const updatedCheckout = await payload.update({
 | 
				
			||||||
 | 
					      collection: 'checkouts',
 | 
				
			||||||
 | 
					      id: checkoutId,
 | 
				
			||||||
 | 
					      data: {
 | 
				
			||||||
 | 
					        loaneeReturnedDate: new Date().toDateString(),
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    return updatedCheckout
 | 
				
			||||||
 | 
					  } catch (err) {
 | 
				
			||||||
 | 
					    console.log(err)
 | 
				
			||||||
 | 
					    return null
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const ownerReturnCheckout = async (props: Props): Promise<Checkout | null> => {
 | 
				
			||||||
 | 
					  const { checkoutId } = props
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const payloadConfig = await config
 | 
				
			||||||
 | 
					  const payload = await getPayload({ config: payloadConfig })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    const updatedCheckout = await payload.update({
 | 
				
			||||||
 | 
					      collection: 'checkouts',
 | 
				
			||||||
 | 
					      id: checkoutId,
 | 
				
			||||||
 | 
					      data: {
 | 
				
			||||||
 | 
					        ownerVerifiedReturnedDate: new Date().toString(),
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    return updatedCheckout
 | 
				
			||||||
 | 
					  } catch (_) {
 | 
				
			||||||
 | 
					    return null
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user