Skip to content

Commit cdef46f

Browse files
authored
Merge branch 'main' into gia2/UI-inconsistencies
2 parents 47e6678 + b7f9758 commit cdef46f

5 files changed

Lines changed: 144 additions & 104 deletions

File tree

‎src/app/donorOffers/[donorOfferId]/page.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export default function DonorOfferDetailsPage() {
2020

2121
// Partners should use the unified items screen at /items instead
2222
if (isPartner(session.user.type)) {
23-
redirect("/");
23+
redirect("/items");
2424
}
2525

2626
const { data, isLoading } = useFetch<{

‎src/components/AddToWishlistModal.tsx‎

Lines changed: 100 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -224,114 +224,118 @@ export default function AddToWishlistModal({
224224
<form onSubmit={handleSubmit} className="space-y-5">
225225
{step === 1 && (
226226
<>
227-
<ModalFormRow>
228-
<ModalTextField
229-
label="Title"
230-
name="name"
231-
placeholder="Placeholder name"
232-
required
233-
value={form.name}
234-
inputProps={{ "data-tutorial": "wishlist-title-input" }}
235-
onChange={(e) => {
236-
setForm((f) => ({ ...f, name: e.target.value }));
237-
setSuggestions([]);
238-
}}
239-
/>
240-
</ModalFormRow>
227+
<div data-tutorial="wishlist-title-field">
228+
<ModalFormRow>
229+
<div className="grow" data-tutorial="wishlist-title-input-box">
230+
<ModalTextField
231+
label="Title"
232+
name="name"
233+
placeholder="Placeholder name"
234+
required
235+
value={form.name}
236+
onChange={(e) => {
237+
setForm((f) => ({ ...f, name: e.target.value }));
238+
setSuggestions([]);
239+
}}
240+
/>
241+
</div>
242+
</ModalFormRow>
243+
</div>
241244

242-
{/* Suggestions block (red highlighted) */}
243-
{showSuggestions && (
244-
<>
245-
<div
246-
className="rounded-lg border border-red-primary bg-red-50/50 p-3 md:p-4"
247-
data-tutorial="wishlist-suggestions"
248-
>
249-
<div className="mb-3">
250-
{effectiveHardMatch ? (
251-
<h3 className="text-red-primary font-semibold text-lg">
252-
This item already exists in our inventory. <br />{" "}
253-
Please request that item instead.
254-
</h3>
245+
<div data-tutorial="wishlist-suggestions">
246+
{/* Suggestions block (red highlighted) */}
247+
{showSuggestions && (
248+
<>
249+
<div className="rounded-lg border border-red-primary bg-red-50/50 p-3 md:p-4">
250+
<div className="mb-3">
251+
{effectiveHardMatch ? (
252+
<h3 className="text-red-primary font-semibold text-lg">
253+
This item already exists in our inventory. <br />{" "}
254+
Please request that item instead.
255+
</h3>
256+
) : (
257+
<h3 className="text-red-primary font-semibold text-lg">
258+
Similar items are in our inventory. <br /> Please go
259+
to Items Page if any of these match.
260+
</h3>
261+
)}
262+
</div>
263+
264+
{isTutorialSuggestions ? (
265+
<div className="overflow-hidden rounded border border-red-primary/25 bg-white">
266+
<div className="grid grid-cols-2 bg-red-primary/80 px-4 py-2 text-sm font-medium text-white">
267+
<span>Title</span>
268+
<span>Quantity</span>
269+
</div>
270+
{displaySuggestions.map((suggestion) => (
271+
<div
272+
key={suggestion.id}
273+
className="grid grid-cols-2 border-t border-gray-100 px-4 py-2 text-sm text-gray-900"
274+
>
275+
<span>{suggestion.title}</span>
276+
<span>{suggestion.quantity ?? "-"}</span>
277+
</div>
278+
))}
279+
</div>
255280
) : (
256-
<h3 className="text-red-primary font-semibold text-lg">
257-
Similar items are in our inventory. <br /> Please go
258-
to Items Page if any of these match.
259-
</h3>
281+
<AdvancedBaseTable<AddToWishlistSuggestion>
282+
columns={suggestionColumns}
283+
fetchFn={suggestionFetchFn}
284+
rowId="id"
285+
headerClassName="bg-red-primary/80 text-white"
286+
rowCellStyles="border border-transparent bg-white"
287+
emptyState={
288+
<div className="py-3 text-sm text-red-700">
289+
No similar items found.
290+
</div>
291+
}
292+
toolBar={null}
293+
disablePagination
294+
disableFilters
295+
/>
260296
)}
261297
</div>
262298

263-
{isTutorialSuggestions ? (
264-
<div className="overflow-hidden rounded border border-red-primary/25 bg-white">
265-
<div className="grid grid-cols-2 bg-red-primary/80 px-4 py-2 text-sm font-medium text-white">
266-
<span>Title</span>
267-
<span>Quantity</span>
268-
</div>
269-
{displaySuggestions.map((suggestion) => (
270-
<div
271-
key={suggestion.id}
272-
className="grid grid-cols-2 border-t border-gray-100 px-4 py-2 text-sm text-gray-900"
273-
>
274-
<span>{suggestion.title}</span>
275-
<span>{suggestion.quantity ?? "-"}</span>
276-
</div>
277-
))}
278-
</div>
279-
) : (
280-
<AdvancedBaseTable<AddToWishlistSuggestion>
281-
columns={suggestionColumns}
282-
fetchFn={suggestionFetchFn}
283-
rowId="id"
284-
headerClassName="bg-red-primary/80 text-white"
285-
rowCellStyles="border border-transparent bg-white"
286-
emptyState={
287-
<div className="py-3 text-sm text-red-700">
288-
No similar items found.
289-
</div>
290-
}
291-
toolBar={null}
292-
disablePagination
293-
disableFilters
294-
/>
295-
)}
296-
</div>
297-
298-
<div className="mt-6 flex gap-4">
299-
<Link
300-
href={`/items?initialItems=${encodeURIComponent(
301-
JSON.stringify(displaySuggestions.map((s) => s.id))
302-
)}`}
303-
className="inline-block w-1/2 rounded-lg border border-red-primary px-4 py-2 font-medium text-red-primary hover:bg-red-50 active:translate-y-px text-center"
304-
>
305-
Go to Items Page
306-
</Link>
299+
<div className="mt-6 flex gap-4">
300+
<Link
301+
href={`/items?initialItems=${encodeURIComponent(
302+
JSON.stringify(displaySuggestions.map((s) => s.id))
303+
)}`}
304+
className="inline-block w-1/2 rounded-lg border border-red-primary px-4 py-2 font-medium text-red-primary hover:bg-red-50 active:translate-y-px text-center"
305+
>
306+
Go to Items Page
307+
</Link>
308+
309+
{/* Continue → Step 2 */}
310+
<button
311+
type="button"
312+
onClick={goToStep2}
313+
disabled={effectiveHardMatch || !form.name.trim()}
314+
className={`w-1/2 rounded-lg px-4 py-2 font-medium text-white active:translate-y-px ${
315+
effectiveHardMatch || !form.name.trim()
316+
? "bg-red-300 cursor-not-allowed"
317+
: "bg-red-primary hover:brightness-95"
318+
}`}
319+
>
320+
Continue with Wish
321+
</button>
322+
</div>
323+
</>
324+
)}
307325

308-
{/* Continue → Step 2 */}
326+
{/* No suggestions but non-empty title */}
327+
{!searching &&
328+
displaySuggestions.length === 0 &&
329+
form.name !== "" && (
309330
<button
310331
type="button"
311332
onClick={goToStep2}
312-
disabled={effectiveHardMatch || !form.name.trim()}
313-
className={`w-1/2 rounded-lg px-4 py-2 font-medium text-white active:translate-y-px ${
314-
effectiveHardMatch || !form.name.trim()
315-
? "bg-red-300 cursor-not-allowed"
316-
: "bg-red-primary hover:brightness-95"
317-
}`}
333+
className="w-full rounded-lg px-4 py-2 font-medium text-white active:translate-y-px bg-red-primary hover:brightness-95"
318334
>
319335
Continue with Wish
320336
</button>
321-
</div>
322-
</>
323-
)}
324-
325-
{/* No suggestions but non-empty title */}
326-
{!searching && displaySuggestions.length === 0 && form.name !== "" && (
327-
<button
328-
type="button"
329-
onClick={goToStep2}
330-
className="w-full rounded-lg px-4 py-2 font-medium text-white active:translate-y-px bg-red-primary hover:brightness-95"
331-
>
332-
Continue with Wish
333-
</button>
334-
)}
337+
)}
338+
</div>
335339
</>
336340
)}
337341

‎src/components/Tutorial.tsx‎

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ export default function Tutorial({
8080
const [stepIndex, setStepIndex] = useState(0);
8181
const [run, setRun] = useState(false);
8282
const [viewportWidth, setViewportWidth] = useState<number | null>(null);
83+
const [isCompletionSynced, setIsCompletionSynced] = useState(false);
8384
const [serverTutorialCompleted, setServerTutorialCompleted] = useState<
8485
boolean | null
8586
>(null);
@@ -264,11 +265,15 @@ export default function Tutorial({
264265
useEffect(() => {
265266
hasFetchedCompletionRef.current = false;
266267
lastNotifiedStepIndexRef.current = null;
268+
setIsCompletionSynced(false);
267269
setServerTutorialCompleted(null);
268270
}, [type, user?.id]);
269271

270272
useEffect(() => {
271273
if (!user?.id || hasFetchedCompletionRef.current) {
274+
if (!user?.id) {
275+
setIsCompletionSynced(true);
276+
}
272277
return;
273278
}
274279

@@ -283,6 +288,7 @@ export default function Tutorial({
283288
if (!response.ok) {
284289
if (!cancelled) {
285290
setServerTutorialCompleted(sessionTutorialCompleted);
291+
setIsCompletionSynced(true);
286292
}
287293
return;
288294
}
@@ -299,6 +305,7 @@ export default function Tutorial({
299305
[tutorialField]: latestValue,
300306
});
301307
}
308+
setIsCompletionSynced(true);
302309
return;
303310
}
304311
} catch (error) {
@@ -307,6 +314,7 @@ export default function Tutorial({
307314

308315
if (!cancelled) {
309316
setServerTutorialCompleted(sessionTutorialCompleted);
317+
setIsCompletionSynced(true);
310318
}
311319
})();
312320

@@ -316,7 +324,12 @@ export default function Tutorial({
316324
}, [sessionTutorialCompleted, tutorialField, updateSession, user?.id]);
317325

318326
useEffect(() => {
319-
if (!user || isTutorialCompleted || tutorialSteps.length === 0) {
327+
if (
328+
!user ||
329+
!isCompletionSynced ||
330+
isTutorialCompleted ||
331+
tutorialSteps.length === 0
332+
) {
320333
return;
321334
}
322335

@@ -330,7 +343,7 @@ export default function Tutorial({
330343
setStepIndex(0);
331344
setRun(true);
332345
notifyStepChange(initialOriginalIndex);
333-
}, [isTutorialCompleted, notifyStepChange, tutorialSteps, user]);
346+
}, [isCompletionSynced, isTutorialCompleted, notifyStepChange, tutorialSteps, user]);
334347

335348
useEffect(() => {
336349
if (!run || responsiveTutorialEntries.length === 0) {
@@ -501,7 +514,12 @@ export default function Tutorial({
501514
}
502515
}, [finishTutorial, notifyStepChange]);
503516

504-
if (!user || isTutorialCompleted || tutorialSteps.length === 0) {
517+
if (
518+
!user ||
519+
!isCompletionSynced ||
520+
isTutorialCompleted ||
521+
tutorialSteps.length === 0
522+
) {
505523
return null;
506524
}
507525

‎src/screens/Wishlist/AdminWishlistScreen.tsx‎

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ import AdvancedBaseTable, {
55
FilterList,
66
} from "@/components/baseTable/AdvancedBaseTable";
77
import { useApiClient } from "@/hooks/useApiClient";
8-
import { useCallback } from "react";
8+
import { useCallback, useState } from "react";
99
import WishlistSummary from "@/components/WishlistSummary";
10-
import { ChatTeardropText } from "@phosphor-icons/react";
10+
import { ChatTeardropText, Question } from "@phosphor-icons/react";
1111
import { Tooltip } from "react-tooltip";
1212
import PriorityTag from "@/components/tags/PriorityTag";
1313

1414
export default function AdminWishlistScreen() {
1515
const { apiClient } = useApiClient();
16+
const [totalItems, setTotalItems] = useState<number | null>(null);
1617

1718
const fetch = useCallback(
1819
async (
@@ -29,6 +30,7 @@ export default function AdminWishlistScreen() {
2930
wishlists: (Wishlist & { partner: User })[];
3031
total: number;
3132
}>(`/api/wishlists?${searchParams}`);
33+
setTotalItems(response.total);
3234

3335
return {
3436
data: response.wishlists,
@@ -41,7 +43,20 @@ export default function AdminWishlistScreen() {
4143
return (
4244
<div className="pb-32">
4345
<h1 className="text-2xl font-semibold text-gray-primary">Wishlists</h1>
44-
<WishlistSummary />
46+
{totalItems !== null && totalItems >= 10 ? <WishlistSummary/> :
47+
<div className="flex justify-end -mb-10 mt-8 mr-28">
48+
<Question
49+
size={20}
50+
className="text-gray-primary/60 cursor-help"
51+
data-tooltip-id="wishlist-ai-info"
52+
data-tooltip-content="AI Wishlist Summary is available when Wishlist contains 10 or more entries"
53+
/>
54+
<Tooltip
55+
id="wishlist-ai-info"
56+
className="z-50 max-w-xs"
57+
/>
58+
</div>
59+
}
4560
<AdvancedBaseTable
4661
columns={[
4762
{

‎src/screens/Wishlist/PartnerWishlistScreen.tsx‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,14 +103,16 @@ const tutorialSteps: TutorialStep[] = [
103103
</div>
104104
),
105105
placement: "left",
106+
isFixed: true,
106107
},
107108
{
108-
target: '[data-tutorial="wishlist-title-input"]',
109+
target: '[data-tutorial="wishlist-title-input-box"]',
109110
title: "Adding a Wishlist",
110111
content:
111112
"For this example, we will enter Bottled Water Cases as the item title.",
112113
placement: "left",
113114
isFixed: true,
115+
spotlightPadding: 2,
114116
},
115117
{
116118
target: '[data-tutorial="wishlist-suggestions"]',
@@ -127,6 +129,7 @@ const tutorialSteps: TutorialStep[] = [
127129
</div>
128130
),
129131
placement: "left",
132+
isFixed: true,
130133
},
131134
{
132135
target: "body",

0 commit comments

Comments
 (0)