Skip to content

Commit 8b52f5f

Browse files
hh
1 parent 1585102 commit 8b52f5f

8 files changed

Lines changed: 89 additions & 137 deletions

File tree

components/Layout.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ export default function Layout( { children } ) {
6464
<span className="rounded-full border border-dashed border-white py-1 px-1 font-black text-shadow text-sm">PIC</span>
6565
</div>
6666
</div>
67-
<main className="mx-auto">
68-
<div className="min-h-screen p-3 w-full max-w-screen-2xl">
67+
<main className="min-h-screen mx-auto">
68+
<div className="max-w-full w-auto">
6969
{ children }
7070
</div>
7171
</main>

components/Yugioh/GridView.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ const GridView = ( { aggregatedData, onDeleteCard, onUpdateCard } ) => {
249249
return (
250250
<div
251251
key={ card._id }
252-
className="group relative flex mx-auto w-full h-[550px] max-h-full max-w-[355px] flex-col rounded-xl border border-white/10 bg-black/30 p-4 transition hover:border-indigo-400/50"
252+
className="group relative flex mx-auto max-w-full h-[550px] max-h-full w-[325px] flex-col rounded border border-white/10 bg-black/30 transition hover:border-indigo-400/50"
253253
>
254254
<div className={ `relative flex-1 flip-card ${ isFlipped ? "flipped" : "" }` }>
255255
<div className="flip-card-inner">
@@ -266,15 +266,15 @@ const GridView = ( { aggregatedData, onDeleteCard, onUpdateCard } ) => {
266266
}
267267
} }
268268
>
269-
<div className="relative flex h-full w-full items-center justify-center overflow-hidden rounded border border-white/10 bg-black/40 shadow-lg transition duration-200 group-hover:border-indigo-400/60 dark:border-white/20 dark:bg-gray-900/60">
269+
<div className="relative flex h-full w-full items-center justify-center overflow-hidden rounded border p-4 border-white/10 bg-black/40 shadow-lg transition duration-200 group-hover:border-indigo-400/60 dark:border-white/20 dark:bg-gray-900/60">
270270
<img
271-
className="mx-auto h-full w-full object-contain"
271+
className="mx-auto h-full w-full object-fill aspect-1"
272272
src={ imageSrc }
273273
alt={ `Card Image - ${ card.productName }` }
274274
loading="lazy"
275275
/>
276276
{ ( formatCurrency( card.marketPrice ) || card.rarity || card.printing ) && (
277-
<div className="pointer-events-none absolute inset-x-0 top-0 flex h-full items-end justify-start overflow-hidden rounded-lg p-4">
277+
<div className="pointer-events-none absolute inset-x-0 top-0 flex h-full items-end justify-start overflow-hidden rounded-lg">
278278
<div
279279
aria-hidden="true"
280280
className="absolute inset-x-0 bottom-0 min-h-[24rem] bg-gradient-to-t from-black/80 via-black/30 to-transparent opacity-90"
@@ -291,7 +291,7 @@ const GridView = ( { aggregatedData, onDeleteCard, onUpdateCard } ) => {
291291
) }
292292
</div>
293293
</div>
294-
<div className="flip-card-back flex min-h-[26rem] w-fit flex-col justify-between gap-3 rounded border border-white/10 bg-black/80 p-4 text-white shadow-lg dark:border-white/20 dark:bg-gray-900/80">
294+
<div className="flip-card-back flex min-h-[24rem] w-fit flex-col justify-between gap-3 rounded border border-white/10 bg-black/80 p-4 text-white shadow-lg dark:border-white/20 dark:bg-gray-900/80">
295295
<div className="space-y-3">
296296
<h3 className="text-lg font-semibold text-center text-pretty break-words">{ card.productName }</h3>
297297
<div className="space-y-1 text-xs text-white/70 sm:text-sm">
@@ -326,7 +326,7 @@ const GridView = ( { aggregatedData, onDeleteCard, onUpdateCard } ) => {
326326
</div>
327327
</div>
328328
</div>
329-
<div className="mt-5 space-y-5 rounded-2xl border border-white/10 bg-white/5 p-4 text-sm text-white/80">
329+
<div className="mt-5 space-y-5 rounded border border-white/10 bg-white/5 p-4 text-sm text-white/80">
330330
<div className="flex flex-wrap items-center justify-between gap-4">
331331
<span className="text-xs font-semibold uppercase tracking-wide text-white/60">Quantity</span>
332332
{ edit[ card._id ] === "quantity" ? (

pages/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export default function LandingPage() {
1818
};
1919

2020
return (
21-
<div className="min-h-screen w-full mx-auto flex flex-wrap">
21+
<div className="min-h-screen mx-auto flex flex-wrap overflow-clip inset-1 max-w-full w-auto">
2222
{/* Yu-Gi-Oh! Panel */ }
2323
<div
2424
onClick={ () => goTo( "/yugioh" ) }

pages/login.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,18 @@ export default function LoginPage() {
109109

110110
if ( response.ok ) {
111111
dispatchAuthStateChange( true );
112-
const redirectTarget = resolveRedirectPath( router.query?.from );
113-
await router.push( redirectTarget );
112+
const rawFromParam = Array.isArray( router.query?.from )
113+
? router.query?.from[ 0 ]
114+
: router.query?.from;
115+
const decodedFromParam =
116+
typeof rawFromParam === "string" ? decodeURIComponent( rawFromParam ) : rawFromParam;
117+
const redirectTarget = resolveRedirectPath( decodedFromParam );
118+
119+
if ( typeof window !== "undefined" ) {
120+
window.location.assign( redirectTarget );
121+
} else {
122+
await router.push( redirectTarget );
123+
}
114124
} else {
115125
setError( data?.error || "Login failed. Please try again." );
116126
}

pages/yugioh/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ const Home = () => {
176176
<meta name="keywords" content="javascript,nextjs,price-tracker,trading-card-game,tailwindcss" />
177177
<meta charSet="UTF-8" />
178178
</Head>
179-
<div className="yugioh-bg min-h-screen w-full mx-auto text-center">
179+
<div className="yugioh-bg min-h-screen w-full mx-auto text-center p-2">
180180

181181
<h1 className="text-4xl font-bold mb-8">Welcome to the thing!</h1>
182182

pages/yugioh/my-collection.js

Lines changed: 55 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,8 @@ import CardFilter from "@/components/Yugioh/CardFilter";
1010
import FilterPanel from "@/components/Yugioh/FilterPanel";
1111
import YugiohPagination from "@/components/Yugioh/YugiohPagination";
1212
import { dispatchAuthStateChange } from "@/utils/authState";
13-
import clientPromise from "@/utils/mongo.js";
1413
import jwt from "jsonwebtoken";
1514
import { getTokenFromRequest } from "@/middleware/authenticate";
16-
import { ensureSafeUserId } from "@/utils/securityValidators.js";
1715

1816
const TableView = dynamic( () => import( "@/components/Yugioh/TableView" ), {
1917
ssr: false,
@@ -37,13 +35,13 @@ const ITEMS_PER_PAGE = 12;
3735
const DEFAULT_FILTERS = { rarity: [], condition: [], printing: [] };
3836
const DEFAULT_SORT = { key: "number", direction: "ascending" };
3937

40-
const MyCollection = ( { initialCards = [], initialAuthState = false } ) => {
38+
const MyCollection = ( { initialAuthState = false } ) => {
4139
const router = useRouter();
4240
const [ notification, setNotification ] = useState( { show: false, message: '' } );
43-
const [ cards, setCards ] = useState( () => ( Array.isArray( initialCards ) ? initialCards : [] ) );
41+
const [ cards, setCards ] = useState( [] );
4442
const [ viewMode, setViewMode ] = useState( "grid" );
4543
const [ isAuthenticated, setIsAuthenticated ] = useState( () => Boolean( initialAuthState ) );
46-
const [ isLoading, setIsLoading ] = useState( () => !initialAuthState );
44+
const [ isLoading, setIsLoading ] = useState( true );
4745
const [ isUpdatingPrices, setIsUpdatingPrices ] = useState( false );
4846
const [ searchValue, setSearchValue ] = useState( "" );
4947
const [ filters, setFilters ] = useState( () => ( { ...DEFAULT_FILTERS } ) );
@@ -69,14 +67,6 @@ const MyCollection = ( { initialCards = [], initialAuthState = false } ) => {
6967
}, [] );
7068

7169
useEffect( () => {
72-
if ( initialAuthState ) {
73-
setIsAuthenticated( true );
74-
setCards( Array.isArray( initialCards ) ? initialCards : [] );
75-
setIsLoading( false );
76-
dispatchAuthStateChange( true );
77-
return;
78-
}
79-
8070
let isActive = true;
8171

8272
const initialize = async () => {
@@ -88,20 +78,26 @@ const MyCollection = ( { initialCards = [], initialAuthState = false } ) => {
8878
return;
8979
}
9080

91-
setIsAuthenticated( true );
9281
setCards( data );
82+
setIsAuthenticated( true );
9383
dispatchAuthStateChange( true );
9484
} catch ( error ) {
95-
if ( isActive ) {
96-
console.error( "Error loading collection:", error );
97-
if ( error?.status === 401 ) {
98-
setIsAuthenticated( false );
99-
setCards( [] );
100-
dispatchAuthStateChange( false );
101-
} else {
102-
setIsAuthenticated( true );
103-
dispatchAuthStateChange( true );
104-
}
85+
if ( !isActive ) {
86+
return;
87+
}
88+
89+
console.error( "Error loading collection:", error );
90+
if ( error?.status === 401 ) {
91+
setIsAuthenticated( false );
92+
setCards( [] );
93+
dispatchAuthStateChange( false );
94+
} else {
95+
setIsAuthenticated( true );
96+
setNotification( ( prev ) => ( {
97+
...prev,
98+
show: true,
99+
message: "Failed to load your collection. Please try again.",
100+
} ) );
105101
}
106102
} finally {
107103
if ( isActive ) {
@@ -115,7 +111,7 @@ const MyCollection = ( { initialCards = [], initialAuthState = false } ) => {
115111
return () => {
116112
isActive = false;
117113
};
118-
}, [ fetchCards, initialAuthState, initialCards ] );
114+
}, [ fetchCards ] );
119115

120116
const refreshCollection = useCallback( async () => {
121117
try {
@@ -531,25 +527,9 @@ const MyCollection = ( { initialCards = [], initialAuthState = false } ) => {
531527
<main
532528
className={ `mx-auto w-full px-4 pb-20 pt-10 sm:px-6 lg:px-8 ${ isDesktopFilterOpen ? "lg:pr-80" : "" }` }
533529
>
534-
<div className="hidden pb-4 lg:flex lg:justify-end">
535-
<button
536-
type="button"
537-
onClick={ toggleDesktopFilters }
538-
aria-expanded={ isDesktopFilterOpen }
539-
aria-controls="desktop-filter-panel"
540-
className="inline-flex items-center gap-2 rounded-full border border-white/20 bg-white/10 px-4 py-2 text-sm font-semibold text-white transition hover:border-white/40"
541-
>
542-
<Filter size={ 16 } />
543-
{ isDesktopFilterOpen ? "Hide Filters" : "Show Filters" }
544-
{ activeFilterBadges.length > 0 && (
545-
<span className="ml-2 rounded-full bg-indigo-500/40 px-2 py-0.5 text-xs font-semibold text-indigo-50">
546-
{ activeFilterBadges.length }
547-
</span>
548-
) }
549-
</button>
550-
</div>
551-
<header className="rounded-3xl border border-white/10 bg-black/40 p-8 shadow-2xl">
552-
<div className="flex flex-col gap-6 lg:flex-row lg:items-end lg:justify-between">
530+
531+
<header className="rounded-xl border border-white/10 bg-black/40 p-8 shadow-2xl">
532+
<div className="flex flex-wrap flex-col lg:flex-row lg:items-end lg:justify-between">
553533
<div className="text-center lg:text-left">
554534
<p className="text-xs font-semibold uppercase tracking-[0.35em] text-white/50">Collection</p>
555535
<h1 className="mt-4 text-3xl font-bold md:text-4xl">My Yu-Gi-Oh! Collection</h1>
@@ -558,17 +538,17 @@ const MyCollection = ( { initialCards = [], initialAuthState = false } ) => {
558538
</p>
559539
</div>
560540
{ hasCards && (
561-
<div className="grid gap-4 text-left sm:grid-cols-3">
562-
<div className="rounded-2xl border border-white/10 bg-white/5 p-5">
563-
<p className="text-xs uppercase tracking-wide text-white/60">Total cards</p>
541+
<div className="grid gap-2 text-left sm:grid-cols-3 mt-3">
542+
<div className="bg-white/5">
543+
<p className="text-wrap text-xs uppercase tracking-wide text-white/60">Total cards</p>
564544
<p className="mt-2 text-3xl font-semibold text-white">{ totalOwnedCards }</p>
565545
</div>
566-
<div className="rounded-2xl border border-white/10 bg-white/5 p-5">
567-
<p className="text-xs uppercase tracking-wide text-white/60">Distinct sets</p>
546+
<div className="bg-white/5">
547+
<p className="text-wrap text-xs uppercase tracking-wide text-white/60">Distinct sets</p>
568548
<p className="mt-2 text-3xl font-semibold text-white">{ distinctSets }</p>
569549
</div>
570-
<div className="rounded-2xl border border-white/10 bg-white/5 p-5">
571-
<p className="text-xs uppercase tracking-wide text-white/60">Estimated value</p>
550+
<div className="bg-white/5">
551+
<p className="text-wrap text-xs uppercase tracking-wide text-white/60">Estimated value</p>
572552
<p className="mt-2 text-3xl font-semibold text-emerald-400">{ formattedEstimatedValue }</p>
573553
</div>
574554
</div>
@@ -634,6 +614,23 @@ const MyCollection = ( { initialCards = [], initialAuthState = false } ) => {
634614
/>
635615
</div>
636616
</div>
617+
<div className="hidden pb-4 lg:flex lg:justify-end">
618+
<button
619+
type="button"
620+
onClick={ toggleDesktopFilters }
621+
aria-expanded={ isDesktopFilterOpen }
622+
aria-controls="desktop-filter-panel"
623+
className="inline-flex items-center gap-2 rounded-full border border-white/20 bg-white/10 px-4 py-2 text-sm font-semibold text-white transition hover:border-white/40"
624+
>
625+
<Filter size={ 16 } />
626+
{ isDesktopFilterOpen ? "Hide Filters" : "Show Filters" }
627+
{ activeFilterBadges.length > 0 && (
628+
<span className="ml-2 rounded-full bg-indigo-500/40 px-2 py-0.5 text-xs font-semibold text-indigo-50">
629+
{ activeFilterBadges.length }
630+
</span>
631+
) }
632+
</button>
633+
</div>
637634
</div>
638635
<div className="mt-6">
639636
<div className="relative">
@@ -715,9 +712,9 @@ const MyCollection = ( { initialCards = [], initialAuthState = false } ) => {
715712
{ isDesktopFilterOpen && (
716713
<aside
717714
id="desktop-filter-panel"
718-
className="hidden lg:fixed lg:inset-y-0 lg:right-0 lg:z-40 lg:flex lg:w-80"
715+
className="hidden lg:fixed lg:inset-y-0 lg:right-0 lg:z-40 lg:flex lg:w-72"
719716
>
720-
<div className="flex h-full w-full flex-col border-l border-white/10 bg-black/40 px-4 py-8 backdrop-blur">
717+
<div className="flex h-full w-full flex-col border-l border-white/10 bg-black/40 px-2 py-8 backdrop-blur">
721718
<FilterPanel
722719
className="h-full overflow-y-auto rounded-2xl border-white/10 bg-black/60 text-white shadow-none"
723720
filters={ filters }
@@ -776,65 +773,11 @@ export async function getServerSideProps( { req } ) {
776773
}
777774
}
778775

779-
let safeUserId;
780-
try {
781-
safeUserId = ensureSafeUserId( decodedUser?.username ?? "" );
782-
} catch {
783-
return {
784-
redirect: {
785-
destination: "/login",
786-
permanent: false,
787-
},
788-
};
789-
}
790-
791-
try {
792-
const client = await clientPromise;
793-
const collection = client.db( "cardPriceApp" ).collection( "myCollection" );
794-
795-
const agg = [
796-
{ $match: { userId: safeUserId } },
797-
{
798-
$project: {
799-
_id: 1,
800-
cardId: 1,
801-
productName: 1,
802-
setName: 1,
803-
number: 1,
804-
printing: 1,
805-
rarity: 1,
806-
condition: 1,
807-
oldPrice: 1,
808-
marketPrice: 1,
809-
lowPrice: 1,
810-
quantity: 1,
811-
},
812-
},
813-
{ $sort: { _id: 1 } },
814-
];
815-
816-
const results = await collection.aggregate( agg ).toArray();
817-
const initialCards = results.map( ( card ) => ( {
818-
...card,
819-
_id: card._id?.toString?.() ?? null,
820-
cardId: card.cardId === null || card.cardId === undefined ? null : String( card.cardId ),
821-
} ) );
822-
823-
return {
824-
props: {
825-
initialCards,
826-
initialAuthState: true,
827-
},
828-
};
829-
} catch ( error ) {
830-
console.error( "getServerSideProps my-collection error:", error );
831-
return {
832-
props: {
833-
initialCards: [],
834-
initialAuthState: false,
835-
},
836-
};
837-
}
776+
return {
777+
props: {
778+
initialAuthState: Boolean( decodedUser ),
779+
},
780+
};
838781
}
839782

840783
export default MyCollection;

0 commit comments

Comments
 (0)