Feat/team owner booking (#3999)

* WIP: testing queries

* feat: add badge

* fix: get only id

* refactor: get bookings query

* WIP: display attendees added

* fix: add type
pull/4402/head^2
Udit Takkar 2022-09-13 02:11:59 +05:30 committed by GitHub
parent 7e52e3d295
commit 1deca816bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 120 additions and 8 deletions

View File

@ -327,8 +327,14 @@ function BookingListItem(booking: BookingItemProps) {
"max-w-56 truncate text-sm font-medium leading-6 text-neutral-900 md:max-w-max", "max-w-56 truncate text-sm font-medium leading-6 text-neutral-900 md:max-w-max",
isCancelled ? "line-through" : "" isCancelled ? "line-through" : ""
)}> )}>
{booking.eventType?.team && <strong>{booking.eventType.team.name}: </strong>}
{booking.title} {booking.title}
<span> </span>
{booking.eventType?.team && <Badge variant="gray">{booking.eventType.team.name}</Badge>}
{!!booking?.eventType?.price && !booking.paid && (
<Tag className="hidden ltr:ml-2 rtl:mr-2 sm:inline-flex">Pending payment</Tag>
)}
{isPending && <Tag className="hidden ltr:ml-2 rtl:mr-2 sm:inline-flex">{t("unconfirmed")}</Tag>}
</div> </div>
{booking.description && ( {booking.description && (
<div <div
@ -337,14 +343,12 @@ function BookingListItem(booking: BookingItemProps) {
&quot;{booking.description}&quot; &quot;{booking.description}&quot;
</div> </div>
)} )}
{booking.attendees.length !== 0 && ( {booking.attendees.length !== 0 && (
<a <DisplayAttendees
className="text-sm text-gray-900 hover:text-blue-500" attendees={booking.attendees}
href={"mailto:" + booking.attendees[0].email} user={booking.user}
onClick={(e) => e.stopPropagation()}> currentEmail={user?.email}
{booking.attendees[0].email} />
</a>
)} )}
{isCancelled && booking.rescheduled && ( {isCancelled && booking.rescheduled && (
<div className="mt-2 inline-block text-left text-sm md:hidden"> <div className="mt-2 inline-block text-left text-sm md:hidden">
@ -373,4 +377,97 @@ function BookingListItem(booking: BookingItemProps) {
); );
} }
interface UserProps {
id: number;
name: string | null;
email: string;
}
const FirstAttendee = ({
user,
currentEmail,
}: {
user: UserProps;
currentEmail: string | null | undefined;
}) => {
return user.email === currentEmail ? (
<div className="inline-block">You</div>
) : (
<a
key={user.email}
className=" hover:text-blue-500"
href={"mailto:" + user.email}
onClick={(e) => e.stopPropagation()}>
{user.name}
</a>
);
};
const Attendee: React.FC<{ email: string; children: React.ReactNode }> = ({ email, children }) => {
return (
<a className=" hover:text-blue-500" href={"mailto:" + email} onClick={(e) => e.stopPropagation()}>
{children}
</a>
);
};
interface AttendeeProps {
name: string;
email: string;
}
const DisplayAttendees = ({
attendees,
user,
currentEmail,
}: {
attendees: AttendeeProps[];
user: UserProps | null;
currentEmail: string | null | undefined;
}) => {
if (attendees.length === 1) {
return (
<div className="text-sm text-gray-900">
{user && <FirstAttendee user={user} currentEmail={currentEmail} />}
<span>&nbsp;and&nbsp;</span>
<Attendee email={attendees[0].email}>{attendees[0].name}</Attendee>
</div>
);
} else if (attendees.length === 2) {
return (
<div className="text-sm text-gray-900">
{user && <FirstAttendee user={user} currentEmail={currentEmail} />}
<span>,&nbsp;</span>
<Attendee email={attendees[0].email}>{attendees[0].name}</Attendee>
<div className="inline-block text-sm text-gray-900">&nbsp;and&nbsp;</div>
<Attendee email={attendees[1].email}>{attendees[1].name}</Attendee>
</div>
);
} else {
return (
<div className="text-sm text-gray-900">
{user && <FirstAttendee user={user} currentEmail={currentEmail} />}
<span>,&nbsp;</span>
<Attendee email={attendees[0].email}>{attendees[0].name}</Attendee>
<span>&nbsp;&&nbsp;</span>
<Tooltip
content={attendees.slice(1).map((attendee, key) => (
<p key={key}>{attendee.name}</p>
))}>
<div className="inline-block">{attendees.length - 1} more</div>
</Tooltip>
</div>
);
}
};
const Tag = ({ children, className = "" }: React.PropsWithChildren<{ className?: string }>) => {
return (
<span
className={`inline-flex items-center rounded-sm bg-yellow-100 px-1.5 py-0.5 text-xs font-medium text-yellow-800 ${className}`}>
{children}
</span>
);
};
export default BookingListItem; export default BookingListItem;

View File

@ -510,6 +510,7 @@ const loggedInViewerRouter = createProtectedRouter()
}; };
const passedBookingsFilter = bookingListingFilters[bookingListingByStatus]; const passedBookingsFilter = bookingListingFilters[bookingListingByStatus];
const orderBy = bookingListingOrderby[bookingListingByStatus]; const orderBy = bookingListingOrderby[bookingListingByStatus];
const bookingsQuery = await prisma.booking.findMany({ const bookingsQuery = await prisma.booking.findMany({
where: { where: {
OR: [ OR: [
@ -523,6 +524,18 @@ const loggedInViewerRouter = createProtectedRouter()
}, },
}, },
}, },
{
eventType: {
team: {
members: {
some: {
userId: user.id,
role: "OWNER",
},
},
},
},
},
], ],
AND: [passedBookingsFilter], AND: [passedBookingsFilter],
}, },
@ -550,6 +563,8 @@ const loggedInViewerRouter = createProtectedRouter()
user: { user: {
select: { select: {
id: true, id: true,
name: true,
email: true,
}, },
}, },
rescheduled: true, rescheduled: true,