Skip to content

Commit

Permalink
Merge branch 'phase-2' of https://github.com/proofcarryingdata/zupass
Browse files Browse the repository at this point in the history
…into phase-2
  • Loading branch information
17Amir17 committed Sep 26, 2024
2 parents 4803f41 + 810a138 commit 4872136
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 30 deletions.
1 change: 1 addition & 0 deletions apps/passport-client/components/shared/PCDCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ export function CardBody({
const Component = PODTicketPCDUI.renderCardBody;
return (
<Component
newUI={newUI}
pcd={pcd}
idBasedVerifyURL={`${window.location.origin}/#/generic-checkin`}
/>
Expand Down
89 changes: 59 additions & 30 deletions apps/passport-client/new-components/screens/Home/NewHomeScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { ChevronLeftIcon, ChevronRightIcon } from "@heroicons/react/24/solid";
import { EdDSATicketPCD, ITicketData } from "@pcd/eddsa-ticket-pcd";
import {
EdDSATicketPCD,
EdDSATicketPCDTypeName,
ITicketData,
isEdDSATicketPCD
} from "@pcd/eddsa-ticket-pcd";
import { Spacer } from "@pcd/passport-ui";
import { PCD } from "@pcd/pcd-types";
import {
Expand All @@ -18,32 +23,52 @@ import { FloatingMenu } from "../../shared/FloatingMenu";
import { CardBody } from "../../../components/shared/PCDCard";
import { TicketCard } from "../../shared/TicketCard";
import { NewModals } from "../../shared/Modals/NewModals";
import {
PODTicketPCD,
PODTicketPCDTypeName,
isPODTicketPCD
} from "@pcd/pod-ticket-pcd";

const GAP = 4;
const ANOTHER_GAP = 40;
const SHOW_HELPER_LINES = false;
const isEventTicketPCD = (
pcd: PCD<unknown, unknown>
): pcd is EdDSATicketPCD => {
const typedPcd = pcd as EdDSATicketPCD;
const TICKET_HEIGHT = 401;
const TICKET_GAP = 20;
type TicketType = EdDSATicketPCD | PODTicketPCD;

const isEventTicketPCD = (pcd: PCD<unknown, unknown>): pcd is TicketType => {
// TODO: fetch the pods type as well and prioritize it if theres a conflict.
return typedPcd.type === "eddsa-ticket-pcd" && !!typedPcd?.claim?.ticket;
return isEdDSATicketPCD(pcd) || isPODTicketPCD(pcd);
};
const useTickets = (): Map<string, EdDSATicketPCD[]> => {
const useTickets = (): Array<[string, TicketType[]]> => {
const allPCDs = usePCDs();
const tickets = allPCDs.filter(isEventTicketPCD);
const eventsMap = new Map<string, EdDSATicketPCD[]>();
const eventsMap = new Map<string, TicketType[]>();

for (const ticket of tickets) {
const ticketList = eventsMap.get(ticket.claim.ticket.eventName) ?? [];
const existingTicketIndex = ticketList.findIndex(
(value) => value.claim.ticket.ticketId === ticket.claim.ticket.ticketId
);

// we prioritize POD tickets, so in case we encounter one, we remove the eddesa ticket.
// if we counter eddesa ticket we check if we have the pod one and if so, ignore eddesa.
if (existingTicketIndex >= 0 && ticket.type === PODTicketPCDTypeName) {
ticketList.splice(existingTicketIndex);
} else if (
existingTicketIndex >= 0 &&
ticket.type === EdDSATicketPCDTypeName
) {
continue;
}

if (!eventsMap.get(ticket.claim.ticket.eventName)) {
eventsMap.set(ticket.claim.ticket.eventName, ticketList);
}

ticketList.push(ticket);
}
return eventsMap;
return Array.from(eventsMap.entries());
};
const Scroller = styled.div<{
amount: number;
Expand All @@ -55,7 +80,7 @@ const Scroller = styled.div<{
flex-direction: row;
gap: ${({ gap }): number => gap}px;
position: relative;
transition: 0.2s cubic-bezier(0.25, 0.8, 0.5, 1);
transition: left 0.2s cubic-bezier(0.25, 0.8, 0.5, 1);
left: ${({ scrollInPx }): number => -scrollInPx}px;
transform: translateX(${({ offset }): number => offset}px);
`;
Expand All @@ -70,11 +95,12 @@ const Line = styled.div<{ padding: number }>`
z-index: 100;
`;

const Container = styled.div<{ elWidth: number }>`
const Container = styled.div<{ elWidth: number; height?: number }>`
margin-top: 20px;
width: 100%;
overflow: hidden;
position: relative;
height: ${({ height }): string => `${height}px` ?? "100%"};
`;

const disabledCSS = css`
Expand Down Expand Up @@ -115,7 +141,8 @@ const TicketsContainer = styled.div`
width: 100%;
display: flex;
flex-direction: column;
gap: 20px;
height: 100%;
gap: ${TICKET_GAP}px;
`;

const positionInPx = (
Expand All @@ -137,11 +164,10 @@ const calculateElWidth = (
return Math.ceil((scrollWidth - gap * (len - 1)) / len);
};

const getEventDetails = (tickets: EdDSATicketPCD[]): ITicketData => {
return (
tickets.find((ticket) => !!ticket.claim.ticket.imageUrl)?.claim.ticket ??
tickets[0].claim.ticket
);
const getEventDetails = (tickets: TicketType[]): ITicketData => {
const ticket = tickets.find((ticket) => !!ticket.claim.ticket.imageUrl)?.claim
.ticket;
return (ticket as ITicketData) ?? (tickets[0].claim.ticket as ITicketData);
};

export const NewHomeScreen = (): ReactElement => {
Expand All @@ -152,9 +178,9 @@ export const NewHomeScreen = (): ReactElement => {
const [width2, setWidth2] = useState(0);
const scrollRef = useRef<HTMLDivElement>(null);
const pcdCardScrollRef = useRef<HTMLDivElement>(null);
const exampleTicketRef = useRef<HTMLDivElement>(null);
const self = useSelf();
const navigate = useNavigate();

useEffect(() => {
if (!self) {
navigate("/new/login", { replace: true });
Expand All @@ -164,19 +190,19 @@ export const NewHomeScreen = (): ReactElement => {
useLayoutEffect(() => {
if (scrollRef.current) {
setWidth(
calculateElWidth(scrollRef.current.scrollWidth, GAP, tickets.size)
calculateElWidth(scrollRef.current.scrollWidth, GAP, tickets.length)
);
}
if (pcdCardScrollRef.current) {
setWidth2(
calculateElWidth(
pcdCardScrollRef.current.scrollWidth,
ANOTHER_GAP,
tickets.size
tickets.length
)
);
}
}, [setWidth, setWidth2, tickets.size]);
}, [setWidth, setWidth2, tickets.length]);

return (
<AppContainer bg="gray" noPadding>
Expand All @@ -185,10 +211,10 @@ export const NewHomeScreen = (): ReactElement => {
gap={GAP}
offset={(420 - width) / 2}
ref={scrollRef}
scrollInPx={positionInPx(currentPos, width, tickets.size - 1, GAP)}
amount={tickets.size - 1}
scrollInPx={positionInPx(currentPos, width, tickets.length - 1, GAP)}
amount={tickets.length - 1}
>
{Array.from(tickets).map(([eventName, eventTickets], i) => {
{tickets.map(([eventName, eventTickets], i) => {
console.log(eventTickets);
const eventDetails = getEventDetails(eventTickets);
return (
Expand Down Expand Up @@ -227,12 +253,12 @@ export const NewHomeScreen = (): ReactElement => {
/>
</PageCircleButton>
<PageCircleButton
disabled={currentPos === tickets.size - 1}
disabled={currentPos === tickets.length - 1}
padding={6}
diameter={28}
onClick={() => {
setCurrentPos((old) => {
if (old === tickets.size - 1) return old;
if (old === tickets.length - 1) return old;
return old + 1;
});
}}
Expand All @@ -245,20 +271,23 @@ export const NewHomeScreen = (): ReactElement => {
</PageCircleButton>
</ButtonsContainer>
<Spacer h={20} />
<Container elWidth={width2}>
<Container
elWidth={width2}
height={(TICKET_HEIGHT + TICKET_GAP) * tickets[currentPos][1].length}
>
<Scroller
gap={ANOTHER_GAP}
ref={pcdCardScrollRef}
scrollInPx={positionInPx(
currentPos,
width2,
tickets.size,
tickets.length,
ANOTHER_GAP
)}
offset={(420 - width2) / 2}
amount={tickets.size - 1}
amount={tickets.length - 1}
>
{Array.from(tickets).map(([_eventName, eventTickets]) => {
{tickets.map(([_eventName, eventTickets]) => {
return (
<TicketsContainer>
{eventTickets.map((ticket) => (
Expand Down
68 changes: 68 additions & 0 deletions packages/ui/pod-ticket-pcd-ui/src/CardBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import urlJoin from "url-join";

export interface PODTicketPCDCardProps {
idBasedVerifyURL: string;
newUI?: boolean;
}

export const PODTicketPCDUI: PCDUI<PODTicketPCD, PODTicketPCDCardProps> = {
Expand All @@ -14,14 +15,42 @@ export const PODTicketPCDUI: PCDUI<PODTicketPCD, PODTicketPCDCardProps> = {

function PODTicketCardBody({
pcd,
newUI,
idBasedVerifyURL
}: {
pcd: PODTicketPCD;
idBasedVerifyURL: string;
newUI?: boolean;
}): JSX.Element {
const ticketData = pcd.claim.ticket;
const hasImage = pcd.claim.ticket.imageUrl !== undefined;

if (newUI) {
return (
<NEW_UI__Container>
<div
style={{
minWidth: 320,
minHeight: 320
}}
>
<TicketQR pcd={pcd} idBasedVerifyURL={idBasedVerifyURL} />
</div>
<NEW_UI__InfoContainer>
<NEW_UI__AttendeeName>
{ticketData?.attendeeName
? ticketData.attendeeName.toUpperCase()
: "JOHN DOE"}
</NEW_UI__AttendeeName>
<NEW_UI__ExtraInfoContainer>
<NEW_UI__ExtraInfo>{ticketData?.attendeeEmail}</NEW_UI__ExtraInfo>
<NEW_UI__ExtraInfo></NEW_UI__ExtraInfo>
<NEW_UI__ExtraInfo>{ticketData?.ticketName}</NEW_UI__ExtraInfo>
</NEW_UI__ExtraInfoContainer>
</NEW_UI__InfoContainer>
</NEW_UI__Container>
);
}
return (
<Container>
{hasImage && (
Expand Down Expand Up @@ -124,3 +153,42 @@ function TicketImage({
</div>
);
}

const NEW_UI__Container = styled.div`
font-family: Barlow;
border-radius: 16px;
border: 2px solid var(--text-white, #fff);
background: var(--bg-white-transparent, rgba(255, 255, 255, 0.8));
/* shadow-sm */
box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.05);
padding: 16px;
`;

const NEW_UI__InfoContainer = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
`;

const NEW_UI__AttendeeName = styled.div`
color: #9a4ac9;
font-size: 20px;
font-style: normal;
font-weight: 800;
line-height: 135%; /* 27px */
`;

const NEW_UI__ExtraInfoContainer = styled.div`
display: flex;
gap: 4px;
`;
const NEW_UI__ExtraInfo = styled.div`
color: var(--text-primary);
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 135%; /* 18.9px */
`;

0 comments on commit 4872136

Please sign in to comment.