Skip to content

Commit

Permalink
New design for booking table (#757)
Browse files Browse the repository at this point in the history
* fully implement new bookings table

* fix type errors

* highlight dietary reqs

* hide non-entered dietary requirements
  • Loading branch information
choden-dev authored Aug 12, 2024
1 parent 6ce5104 commit 5ca6d64
Show file tree
Hide file tree
Showing 10 changed files with 357 additions and 87 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { Meta, StoryObj } from "@storybook/react"
import AdminBookingDate, { BookingInfo } from "./AdminBookingDate"
import { Timestamp } from "firebase/firestore"

const meta: Meta<typeof AdminBookingDate> = {
component: AdminBookingDate
}

export default meta
type Story = StoryObj<typeof meta>

const mockData: BookingInfo = {
bookingId: "djs",
uid: "1",
first_name: "Straight",
last_name: "Zhao",
date_of_birth: Timestamp.fromMillis(0),
phone_number: 69696969,
dietary_requirements: "nothing",
email: "[email protected]",
membership: "guest"
}

const mockDataArray: BookingInfo[] = []

for (let i = 0; i < 100; ++i) {
mockDataArray.push(mockData)
}

export const DefaultAdminBookingDate: Story = {
args: {
dateString: "20/10/2024",
users: mockDataArray
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { CombinedUserData } from "@/models/User"
import BookingUserCard from "./BookingUserCard"

export type BookingInfo = CombinedUserData & { bookingId: string }

export interface IAdminBookingDate {
/**
* The `unique` string representing the date the users are booked for
*/
dateString: string

/**
* For more detailed explaination of the date
*
* @example "Friday"
*/
dayName?: string

/**
* All of the user information associated with the date
*/
users: Readonly<BookingInfo>[]

/**
* Callback for when an attempt is made to delete a booking
*/
handleUserDelete: (id: string) => void
}

/**
* Component to display the available users for each date in a booking
*/
const AdminBookingDate = ({
dateString,
dayName,
users,
handleUserDelete
}: IAdminBookingDate) => {
return (
<div className="border-gray-3 flex h-fit w-full flex-col gap-2 border bg-white p-2">
{dayName && <h5 className="font-bold uppercase underline">{dayName}</h5>}
<h2 className="text-dark-blue-100 italic">{dateString}</h2>
<h5 className="font-bold uppercase">{users.length} Bookings</h5>
<h5 className="uppercase opacity-75">
Tap on user to toggle information
</h5>
{users.map((user, index) => {
return (
<BookingUserCard
user={user}
index={index}
key={user.uid}
handleDelete={handleUserDelete}
/>
)
})}
</div>
)
}

export default AdminBookingDate
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type { Meta, StoryObj } from "@storybook/react"
import { Timestamp } from "firebase/firestore"
import BookingUserCard from "./BookingUserCard"
import { BookingInfo } from "./AdminBookingDate"

const meta: Meta<typeof BookingUserCard> = {
component: BookingUserCard
}

export default meta
type Story = StoryObj<typeof meta>

const mockUser: BookingInfo = {
bookingId: "asd",
uid: "1",
first_name: "Straight",
last_name: "Zhao",
date_of_birth: Timestamp.fromMillis(0),
phone_number: 69696969,
dietary_requirements:
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Soluta enim voluptatum id placeat quod exercitationem vero non amet, minima totam voluptas illo ad ipsa autem odio reiciendis optio vel libero quia, consectetur ipsum molestias repellat distinctio a? Non error minima est beatae nostrum, nam, alias officiis, amet dolorem corrupti doloremque!",
email: "[email protected]",
membership: "guest"
}

export const DefaultAdminBookingDateDisplay: Story = {
args: {
user: mockUser
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { useState } from "react"
import { BookingInfo } from "./AdminBookingDate"

interface IBookingUserCard {
index: number
user: Readonly<BookingInfo>
handleDelete?: (id: string) => void
}

const BookingUserCard = ({ index, user, handleDelete }: IBookingUserCard) => {
const [isOpen, setIsOpen] = useState<boolean>(false)
const hasDietaryRequirements = user.dietary_requirements.trim().length > 0
return (
<div
key={user.uid}
className="border-gray-3 w-full border bg-white px-4 py-2"
>
<div
className="flex w-full cursor-pointer items-center gap-5"
onClick={() => setIsOpen(!isOpen)}
>
<div className="flex flex-col gap-2">
<span className="flex flex-col">
<p className="underline">
<strong>{`#${index}`}</strong> {user.first_name} {user.last_name}
</p>
<h5>{user.membership}</h5>
</span>
{hasDietaryRequirements && (
<div className="border-dark-blue-100 flex w-full flex-col rounded-sm border px-2">
<h5 className="font-bold uppercase">Dietary Reqs</h5>
<p>{user.dietary_requirements}</p>
</div>
)}
</div>
<h5
className="text-red ml-auto cursor-pointer font-bold"
onClick={() => handleDelete?.(user.bookingId)}
>
X
</h5>
</div>
{isOpen && (
<div className="flex flex-col">
<div className="mb-2 mt-4 w-full border" />
<h5>
<strong>Email:</strong> {user.email}
</h5>
<h5>
<strong>Phone Number:</strong> {user.phone_number}
</h5>
<h5>
<strong>Emergency Contact:</strong> {user.emergency_contact}
</h5>
</div>
)}
</div>
)
}

export default BookingUserCard
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import type { Meta, StoryObj } from "@storybook/react"
import AdminBookingDateDisplay from "./AdminBookingDateDisplay"
import { Timestamp } from "firebase/firestore"
import {
BookingInfo,
IAdminBookingDate
} from "./AdminBookingDate/AdminBookingDate"

const meta: Meta<typeof AdminBookingDateDisplay> = {
component: AdminBookingDateDisplay
}

export default meta
type Story = StoryObj<typeof meta>

const mockUser: BookingInfo = {
bookingId: "2323",
uid: "1",
first_name: "Straight",
last_name: "Zhao",
date_of_birth: Timestamp.fromMillis(0),
phone_number: 69696969,
dietary_requirements: "nothing",
email: "[email protected]",
membership: "guest"
}

const mockUsersArray: BookingInfo[] = []

for (let i = 0; i < 32; ++i) {
mockUsersArray.push(mockUser)
}

const mockDatesArray: IAdminBookingDate[] = []

for (let i = 1; i < 30; ++i) {
mockDatesArray.push({
dateString: `${i}/10/2002`,
users: mockUsersArray,
handleUserDelete: () => {}
})
}

export const DefaultAdminBookingDateDisplay: Story = {
args: {
dates: mockDatesArray
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import AdminBookingDate, {
IAdminBookingDate
} from "./AdminBookingDate/AdminBookingDate"

export interface IAdminBookingDateDisplay {
/**
* The list of dates to be displayed to user
*/
dates: IAdminBookingDate[]

/**
* Callback to remove the booking with specified `id` from a booking date
*/
handleDelete?: (id: string) => void
}

const AdminBookingDateDisplay = ({ dates }: IAdminBookingDateDisplay) => {
return (
<div className="flex gap-2">
{dates.map((date) => {
return (
<span key={date.dateString} className="min-w-[340px]">
<AdminBookingDate
dateString={date.dateString}
dayName={date.dayName}
handleUserDelete={date.handleUserDelete}
users={date.users}
/>
</span>
)
})}
</div>
)
}

export default AdminBookingDateDisplay
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import type { Meta, StoryObj } from "@storybook/react"
import AdminBookingView, { BookingMemberColumnFormat } from "./AdminBookingView"
import AdminBookingView from "./AdminBookingView"
import {
BookingInfo,
IAdminBookingDate
} from "./AdminBookingDateDisplay/AdminBookingDate/AdminBookingDate"
import { Timestamp } from "firebase/firestore"

const meta: Meta<typeof AdminBookingView> = {
component: AdminBookingView
Expand All @@ -8,24 +13,37 @@ const meta: Meta<typeof AdminBookingView> = {
export default meta
type Story = StoryObj<typeof meta>

const mockData: BookingMemberColumnFormat = {
const mockUser: BookingInfo = {
bookingId: "23132al",
uid: "1",
Date: "04/06/2004",
Name: "Ray",
Number: "12345678",
Email: "[email protected]",
"Dietary Requirement": "none"
first_name: "Straight",
last_name: "Zhao",
date_of_birth: Timestamp.fromMillis(0),
phone_number: 69696969,
dietary_requirements: "nothing",
email: "[email protected]",
membership: "guest"
}

const mockDataArray: BookingMemberColumnFormat[] = []
const mockUsersArray: BookingInfo[] = []

for (let i = 0; i < 100; ++i) {
mockDataArray.push(mockData)
for (let i = 0; i < 32; ++i) {
mockUsersArray.push(mockUser)
}

const mockDatesArray: IAdminBookingDate[] = []

for (let i = 1; i < 30; ++i) {
mockDatesArray.push({
dateString: `${i}/10/2002`,
users: mockUsersArray,
handleUserDelete: () => {}
})
}

export const DefaultAdminBookingView: Story = {
args: {
data: mockDataArray,
data: mockDatesArray,
dateRange: {
startDate: new Date("6969-10-10"),
endDate: new Date("9696-10-01")
Expand Down
Loading

0 comments on commit 5ca6d64

Please sign in to comment.