Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import {
ChevronRight,
Plus,
Trash2,
ExternalLink,
Search,
ShieldAlert,
} from "lucide-react";
Expand All @@ -53,15 +52,11 @@ import {
} from "@/components/ui/sheet";
import Image from "next/image";
import { ReferrersModal } from "./ReferrersModal";
import {
formatCapacityIssueMessage,
getCapacityIssues,
} from "@/lib/capacity";
import { formatCapacityIssueMessage, getCapacityIssues } from "@/lib/capacity";

export function CheckoutForm({
token,
fundraiser,
userProfile,
code,
}: {
token: string;
Expand All @@ -85,11 +80,10 @@ export function CheckoutForm({
const initialReferralId = fundraiser.referrals.some((r) => r.id === code)
? code
: "none";
const [selectedReferralId, setSelectedReferralId] = useState<string>(
initialReferralId,
);
const [selectedReferralId, setSelectedReferralId] =
useState<string>(initialReferralId);
const [paymentMethod, setPaymentMethod] = useState<"VENMO" | "OTHER">(
"VENMO",
fundraiser.venmoEmail ? "VENMO" : "OTHER",
);
const [isSubmitting, setIsSubmitting] = useState(false);
const [isReferralSheetOpen, setIsReferralSheetOpen] = useState(false);
Expand Down Expand Up @@ -208,7 +202,9 @@ export function CheckoutForm({
availabilityItem?.available !== undefined &&
newQuantity > availabilityItem.available
) {
toast.error(`Only ${availabilityItem.available} available for ${item.name}`);
toast.error(
`Only ${availabilityItem.available} available for ${item.name}`,
);
return;
}
}
Expand Down Expand Up @@ -429,36 +425,43 @@ export function CheckoutForm({
</div>
)}
<span className="text-base">
{paymentMethod === "VENMO" ? "Venmo" : "Cash In-Person"}
{paymentMethod === "VENMO" ? "Venmo" : "Other"}
</span>
</div>
</div>
</SelectTrigger>
<SelectContent>
<SelectItem value="VENMO">
<div className="flex items-center gap-2">
<svg
className="h-7 w-7"
xmlns="http://www.w3.org/2000/svg"
aria-label="Venmo"
role="img"
viewBox="0 0 512 512"
>
<rect width="512" height="512" rx="15%" fill="#008CFF" />
<path
d="m381.4 105.3c11 18.1 15.9 36.7 15.9 60.3 0 75.1-64.1 172.7-116.2 241.2h-118.8l-47.6-285 104.1-9.9 25.3 202.8c23.5-38.4 52.6-98.7 52.6-139.7 0-22.5-3.9-37.8-9.9-50.4z"
fill="#ffffff"
/>
</svg>
<span>Venmo</span>
</div>
</SelectItem>
{fundraiser.venmoEmail && (
<SelectItem value="VENMO">
<div className="flex items-center gap-2">
<svg
className="h-7 w-7"
xmlns="http://www.w3.org/2000/svg"
aria-label="Venmo"
role="img"
viewBox="0 0 512 512"
>
<rect
width="512"
height="512"
rx="15%"
fill="#008CFF"
/>
<path
d="m381.4 105.3c11 18.1 15.9 36.7 15.9 60.3 0 75.1-64.1 172.7-116.2 241.2h-118.8l-47.6-285 104.1-9.9 25.3 202.8c23.5-38.4 52.6-98.7 52.6-139.7 0-22.5-3.9-37.8-9.9-50.4z"
fill="#ffffff"
/>
</svg>
<span>Venmo</span>
</div>
</SelectItem>
)}
<SelectItem value="OTHER">
<div className="flex items-center gap-2">
<div className="h-7 w-7 bg-green-600 rounded flex items-center justify-center text-white font-bold text-[15px]">
$
</div>
<span>Cash In-Person</span>
<span>Other</span>
</div>
</SelectItem>
</SelectContent>
Expand Down Expand Up @@ -794,35 +797,37 @@ export function CheckoutForm({
</div>
</SelectTrigger>
<SelectContent>
<SelectItem value="VENMO">
<div className="flex items-center gap-2">
<svg
className="h-7 w-7"
xmlns="http://www.w3.org/2000/svg"
aria-label="Venmo"
role="img"
viewBox="0 0 512 512"
>
<rect
width="512"
height="512"
rx="15%"
fill="#008CFF"
/>
<path
d="m381.4 105.3c11 18.1 15.9 36.7 15.9 60.3 0 75.1-64.1 172.7-116.2 241.2h-118.8l-47.6-285 104.1-9.9 25.3 202.8c23.5-38.4 52.6-98.7 52.6-139.7 0-22.5-3.9-37.8-9.9-50.4z"
fill="#ffffff"
/>
</svg>
<span>Venmo</span>
</div>
</SelectItem>
{fundraiser.venmoEmail && (
<SelectItem value="VENMO">
<div className="flex items-center gap-2">
<svg
className="h-7 w-7"
xmlns="http://www.w3.org/2000/svg"
aria-label="Venmo"
role="img"
viewBox="0 0 512 512"
>
<rect
width="512"
height="512"
rx="15%"
fill="#008CFF"
/>
<path
d="m381.4 105.3c11 18.1 15.9 36.7 15.9 60.3 0 75.1-64.1 172.7-116.2 241.2h-118.8l-47.6-285 104.1-9.9 25.3 202.8c23.5-38.4 52.6-98.7 52.6-139.7 0-22.5-3.9-37.8-9.9-50.4z"
fill="#ffffff"
/>
</svg>
<span>Venmo</span>
</div>
</SelectItem>
)}
<SelectItem value="OTHER">
<div className="flex items-center gap-2">
<div className="h-7 w-7 bg-green-600 rounded flex items-center justify-center text-white font-bold text-[15px]">
$
</div>
<span>Cash In-Person</span>
<span>Other</span>
</div>
</SelectItem>
</SelectContent>
Expand Down
110 changes: 100 additions & 10 deletions frontend/src/app/seller/fundraiser/[id]/components/Checklist.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
"use client";

import { ReactNode, useEffect, useState } from "react";
import { ReactNode, useEffect, useMemo, useState } from "react";
import { Card } from "@/components/ui/card";
import { cn } from "@/lib/utils";
import {
getSkippedVenmoPreference,
setSkippedVenmoPreference,
} from "@/lib/fundraiserVenmoPreference";
import {
Image,
PencilLine,
Expand All @@ -12,6 +16,7 @@ import {
MoveRight,
ShoppingCart,
Upload,
Check,
} from "lucide-react";
import { CompleteFundraiserSchema, CompleteItemSchema } from "common";
import { z } from "zod";
Expand Down Expand Up @@ -104,7 +109,8 @@ interface ListItem {

const getChecklistStatus = (
fundraiser: z.infer<typeof CompleteFundraiserSchema>,
fundraiserItems: z.infer<typeof CompleteItemSchema>[]
fundraiserItems: z.infer<typeof CompleteItemSchema>[],
skipVenmo: boolean,
) => {
return checkListData.map((item) => {
let completed = false;
Expand All @@ -119,7 +125,9 @@ const getChecklistStatus = (
break;
case "venmoInfo":
completed =
!!fundraiser.venmoUsername?.trim() || !!fundraiser.venmoEmail?.trim();
skipVenmo ||
!!fundraiser.venmoUsername?.trim() ||
!!fundraiser.venmoEmail?.trim();
break;
case "pickupLocation":
completed = fundraiser.pickupEvents.length > 0;
Expand All @@ -141,28 +149,66 @@ const getChecklistStatus = (
export default function ListPage({
fundraiser,
fundraiserItems,
skipVenmoOverride,
onAction,
publish,
isSubmitting,
}: {
fundraiser: z.infer<typeof CompleteFundraiserSchema>;
fundraiserItems: z.infer<typeof CompleteItemSchema>[];
skipVenmoOverride?: boolean;
onAction: (step: number) => void;
publish: () => void;
isSubmitting: boolean;
}) {
const checkListData = getChecklistStatus(fundraiser, fundraiserItems);
const [skipVenmo, setSkipVenmo] = useState(false);
const checkListData = useMemo(
() => getChecklistStatus(fundraiser, fundraiserItems, skipVenmo),
[fundraiser, fundraiserItems, skipVenmo],
);
const [selectedItem, setSelectedItem] = useState<ListItem | null>(
checkListData.find((item) => !item.completed) || null
checkListData.find((item) => !item.completed) || null,
);
const [canPublish, setCanPublish] = useState(false);

useEffect(() => {
if (skipVenmoOverride !== undefined) {
setSkipVenmo(skipVenmoOverride);
return;
}

if (fundraiser.venmoUsername?.trim() || fundraiser.venmoEmail?.trim()) {
setSkipVenmo(false);
return;
}

setSkipVenmo(getSkippedVenmoPreference(fundraiser.id));
}, [
fundraiser.id,
fundraiser.venmoEmail,
fundraiser.venmoUsername,
skipVenmoOverride,
]);

useEffect(() => {
const allCompleted = checkListData.every((item) => item.completed);
const nextIncompleteItem =
checkListData.find((item) => !item.completed) || checkListData[0] || null;

setCanPublish(allCompleted);
if (allCompleted) {
setSelectedItem((prev) => prev ?? checkListData[0]);
}
setSelectedItem((prev) => {
if (!prev) {
return nextIncompleteItem;
}

const refreshedItem = checkListData.find((item) => item.key === prev.key);

if (!refreshedItem || refreshedItem.completed) {
return nextIncompleteItem;
}

return refreshedItem;
});
}, [checkListData]);

return (
Expand All @@ -183,7 +229,7 @@ export default function ListPage({
: "cursor-pointer border-border bg-card hover:border-ring hover:bg-accent",
selectedItem?.key === item.key &&
!item.completed &&
"border-ring bg-accent"
"border-ring bg-accent",
)}
>
<div className="flex items-center gap-3">
Expand All @@ -192,7 +238,7 @@ export default function ListPage({
"h-5 w-5 rounded-full border-[1px] flex items-center justify-center",
item.completed
? "border-muted-foreground"
: "border-foreground"
: "border-foreground",
)}
>
{item.completed && (
Expand Down Expand Up @@ -252,6 +298,50 @@ export default function ListPage({
<MoveRight />
</Button>
)}

<div>
{selectedItem.key === "venmoInfo" && !canPublish && (
<button
type="button"
onClick={() => {
const nextSkipVenmo = !skipVenmo;
setSkipVenmo(nextSkipVenmo);
setSkippedVenmoPreference(
fundraiser.id,
nextSkipVenmo,
);
}}
className={cn(
"flex w-full items-start gap-3 rounded-xl border p-4 text-left transition-all",
"hover:border-[#265B34] hover:bg-green-50/50",
skipVenmo
? "border-[#265B34] bg-green-50"
: "border-border bg-background",
)}
>
<div
className={cn(
"mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-md border",
skipVenmo
? "border-[#265B34] bg-[#265B34] text-white"
: "border-muted-foreground/40 bg-background",
)}
>
{skipVenmo && <Check className="h-3.5 w-3.5" />}
</div>

<div className="space-y-1">
<p className="text-sm font-medium text-foreground">
This fundraiser will not use Venmo
</p>
<p className="text-xs leading-relaxed text-muted-foreground">
Check this if donations for this fundraiser will be
handled without Venmo.
</p>
</div>
</button>
)}
</div>
</div>
) : (
<div className="flex h-64 items-center justify-center">
Expand Down
Loading