Skip to content

Commit 90bf4f5

Browse files
hh
1 parent 654214f commit 90bf4f5

14 files changed

Lines changed: 406 additions & 2279 deletions

File tree

components/Yugioh/Card.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const Card = ( { cardData } ) => {
3535
<Image
3636
as="image"
3737
unoptimized="true"
38-
className="lg:object-contain object-scale-down object-top w-full mx-auto h-96 aspect-1"
38+
className="object-contain lg:object-scale-down object-top w-full mx-auto h-96 aspect-square"
3939
src={ imageSrc }
4040
alt={ `Card Image - ${ productName }` }
4141
width={ 1600 }

components/Yugioh/GridView.js

Lines changed: 60 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,22 @@ const formatCurrency = ( value ) => {
1313
return `$${ numeric.toFixed( 2 ) }`;
1414
};
1515

16-
const GridView = ( { aggregatedData, onDeleteCard, onUpdateCard } ) => {
16+
const GridView = ( { aggregatedData, onDeleteCard, onUpdateCard, sortConfig, handleSortChange } ) => {
1717
const [ edit, setEdit ] = useState( {} );
1818
const [ editValues, setEditValues ] = useState( {} );
1919
const [ notification, setNotification ] = useState( { show: false, message: "" } );
2020
const [ flippedCards, setFlippedCards ] = useState( {} );
21-
const [ sortField, setSortField ] = useState( "setName" );
22-
const [ sortDirection, setSortDirection ] = useState( "asc" );
21+
const isExternallySorted = Boolean( sortConfig && typeof handleSortChange === "function" );
22+
const [ internalSortField, setInternalSortField ] = useState( "setName" );
23+
const [ internalSortDirection, setInternalSortDirection ] = useState( "asc" );
24+
const sortField = isExternallySorted ? sortConfig.key : internalSortField;
25+
const sortDirection = isExternallySorted
26+
? ( sortConfig.direction === "descending" ? "desc" : "asc" )
27+
: internalSortDirection;
2328
const displayInputClasses =
24-
"min-w-[4rem] rounded-lg border border-white/30 bg-black/50 px-3 py-1 text-center font-semibold text-white transition hover:border-white/60 focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-400/60";
29+
"min-w-[4rem] rounded border border-white/30 bg-black/50 px-3 py-1 text-center font-semibold text-white transition hover:border-white/60 focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-400/60";
2530
const displayInputClassesRose =
26-
"min-w-[4rem] rounded-lg border border-rose-300/60 bg-black/50 px-3 py-1 text-center font-semibold text-rose-200 transition hover:border-rose-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-rose-400/60";
31+
"min-w-[4rem] rounded border border-rose-300/60 bg-black/50 px-3 py-1 text-center font-semibold text-rose-200 transition hover:border-rose-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-rose-400/60";
2732

2833
const handleEdit = useCallback(
2934
( cardId, field ) => {
@@ -111,6 +116,10 @@ const GridView = ( { aggregatedData, onDeleteCard, onUpdateCard } ) => {
111116
const memoizedAggregatedData = useMemo( () => {
112117
if ( !Array.isArray( aggregatedData ) ) return [];
113118

119+
if ( isExternallySorted ) {
120+
return aggregatedData;
121+
}
122+
114123
const sortedData = [ ...aggregatedData ];
115124

116125
if ( !sortField ) {
@@ -140,7 +149,29 @@ const GridView = ( { aggregatedData, onDeleteCard, onUpdateCard } ) => {
140149
} );
141150

142151
return sortedData;
143-
}, [ aggregatedData, sortField, sortDirection ] );
152+
}, [ aggregatedData, isExternallySorted, sortField, sortDirection ] );
153+
154+
const handleSortFieldChange = useCallback(
155+
( nextField ) => {
156+
if ( isExternallySorted ) {
157+
handleSortChange( nextField );
158+
return;
159+
}
160+
161+
setInternalSortField( nextField );
162+
},
163+
[ handleSortChange, isExternallySorted ],
164+
);
165+
166+
const toggleSortDirection = useCallback( () => {
167+
if ( isExternallySorted ) {
168+
const nextDirection = sortConfig.direction === "ascending" ? "descending" : "ascending";
169+
handleSortChange( sortConfig.key, nextDirection );
170+
return;
171+
}
172+
173+
setInternalSortDirection( ( prev ) => ( prev === "asc" ? "desc" : "asc" ) );
174+
}, [ handleSortChange, isExternallySorted, sortConfig ] );
144175

145176
return (
146177
<>
@@ -149,12 +180,13 @@ const GridView = ( { aggregatedData, onDeleteCard, onUpdateCard } ) => {
149180
<span className="font-medium text-white/70">Sort</span>
150181
<select
151182
value={ sortField }
152-
onChange={ ( event ) => setSortField( event.target.value ) }
153-
className="rounded-lg border border-white/15 bg-black/60 px-3 py-2 text-sm font-medium text-white/80 shadow-sm transition hover:border-white/40 focus:border-indigo-400 focus:outline-none focus:ring-2 focus:ring-indigo-400/40"
183+
onChange={ ( event ) => handleSortFieldChange( event.target.value ) }
184+
className="rounded border border-white/15 bg-black/60 px-3 py-2 text-sm font-medium text-white/80 shadow-sm transition hover:border-white/40 focus:border-indigo-400 focus:outline-none focus:ring-2 focus:ring-indigo-400/40"
154185
>
155186
<option value="productName">Card Name</option>
156187
<option value="setName">Set Name</option>
157188
<option value="number">Card Number</option>
189+
<option value="printing">Printing</option>
158190
<option value="rarity">Card Rarity</option>
159191
<option value="quantity">Quantity</option>
160192
<option value="marketPrice">Market Price</option>
@@ -163,15 +195,15 @@ const GridView = ( { aggregatedData, onDeleteCard, onUpdateCard } ) => {
163195
</div>
164196
<button
165197
type="button"
166-
onClick={ () => setSortDirection( ( prev ) => ( prev === "asc" ? "desc" : "asc" ) ) }
167-
className="inline-flex items-center rounded-lg border border-white/15 bg-black/60 px-3 py-2 text-sm font-semibold uppercase tracking-wide text-white/80 transition hover:border-white/40 hover:text-white focus:border-indigo-400 focus:outline-none focus:ring-2 focus:ring-indigo-400/40"
198+
onClick={ toggleSortDirection }
199+
className="inline-flex items-center rounded border border-white/15 bg-black/60 px-3 py-2 text-sm font-semibold uppercase tracking-wide text-white/80 transition hover:border-white/40 hover:text-white focus:border-indigo-400 focus:outline-none focus:ring-2 focus:ring-indigo-400/40"
168200
>
169201
{ sortDirection === "asc" ? "Asc" : "Desc" }
170202
</button>
171203
</div>
172204

173-
<div className="w-full rounded-xl border border-white/10 bg-black/40 p-4 shadow-2xl sm:p-2">
174-
<div className="grid grid-cols-1 gap-2 xl:grid-cols-2 2xl:grid-cols-3">
205+
<div className="w-full rounded border border-white/10 bg-black/40 p-4 shadow-2xl sm:p-2">
206+
<div className="grid grid-cols-1 gap-2 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4">
175207
{ memoizedAggregatedData.map( ( card ) => {
176208
if ( !card ) return null;
177209

@@ -249,12 +281,12 @@ const GridView = ( { aggregatedData, onDeleteCard, onUpdateCard } ) => {
249281
return (
250282
<div
251283
key={ card._id }
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"
284+
className="group relative flex flex-wrap mx-auto sm:w-fit lg:w-full min-h-[32rem] flex-col rounded border border-white/10 bg-black/30 transition hover:border-indigo-400/50"
253285
>
254-
<div className={ `relative flex-1 flip-card ${ isFlipped ? "flipped" : "" }` }>
255-
<div className="flip-card-inner">
286+
<div className={ `rounded relative flex-1 flip-card ${ isFlipped ? "flipped" : "" }` }>
287+
<div className="flip-card-inner rounded">
256288
<div
257-
className="flip-card-front flex h-full w-full flex-col gap-4"
289+
className="flip-card-front flex h-[24rem] w-fit flex-col rounded"
258290
role="button"
259291
tabIndex={ 0 }
260292
aria-pressed={ isFlipped }
@@ -266,20 +298,22 @@ const GridView = ( { aggregatedData, onDeleteCard, onUpdateCard } ) => {
266298
}
267299
} }
268300
>
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">
301+
<div className="relative flex h-full w-auto 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">
270302
<img
271-
className="mx-auto h-full w-full object-fill aspect-1"
303+
className="mx-auto h-full w-full object-top object-scale-down aspect-square"
272304
src={ imageSrc }
273305
alt={ `Card Image - ${ card.productName }` }
274306
loading="lazy"
275307
/>
276308
{ ( 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">
309+
<div className="pointer-events-none absolute inset-x-0 top-0 flex h-full items-end justify-start overflow-hidden rounded">
278310
<div
279311
aria-hidden="true"
280312
className="absolute inset-x-0 bottom-0 min-h-[24rem] bg-gradient-to-t from-black/80 via-black/30 to-transparent opacity-90"
281313
/>
282-
<div className="relative flex flex-col gap-1 text-white">
314+
315+
<div className="relative flex flex-col gap-1 text-white p-2 text-shadow glass w-full bg-transparent">
316+
<h3 className="text-lg font-semibold text-pretty break-words">{ card.productName }</h3>
283317
{ formatCurrency( card.marketPrice ) && (
284318
<p className="text-lg font-semibold">{ formatCurrency( card.marketPrice ) }</p>
285319
) }
@@ -291,7 +325,7 @@ const GridView = ( { aggregatedData, onDeleteCard, onUpdateCard } ) => {
291325
) }
292326
</div>
293327
</div>
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">
328+
<div className="flip-card-back flex min-h-[32rem] w-full flex-col justify-between gap-3 rounded border border-white/10 bg-black p-4 text-white shadow-lg dark:border-white/20 dark:bg-gray-900/80">
295329
<div className="space-y-3">
296330
<h3 className="text-lg font-semibold text-center text-pretty break-words">{ card.productName }</h3>
297331
<div className="space-y-1 text-xs text-white/70 sm:text-sm">
@@ -305,9 +339,9 @@ const GridView = ( { aggregatedData, onDeleteCard, onUpdateCard } ) => {
305339
) ) }
306340
</div>
307341
</div>
308-
<div className="mx-auto mt-2 flex w-full flex-col gap-2 text-pretty sm:flex-row sm:gap-3">
342+
<div className="mx-auto mt-2 flex flex-wrap w-full gap-2 text-pretty sm:gap-3">
309343
<Link
310-
className="inline-flex w-full items-center justify-center rounded-md border border-white/20 bg-white/10 px-2 py-1 text-sm font-semibold text-white transition hover:border-indigo-400 hover:bg-indigo-500/20"
344+
className="inline-flex w-full items-center justify-center rounded border border-white/20 bg-white/10 px-2 py-1 text-sm font-semibold text-white transition hover:border-indigo-400 hover:bg-indigo-500/20"
311345
href={ {
312346
pathname: "/yugioh/sets/[letter]/cards/card-details",
313347
query: cardDetailsQuery,
@@ -317,7 +351,7 @@ const GridView = ( { aggregatedData, onDeleteCard, onUpdateCard } ) => {
317351
</Link>
318352
<button
319353
type="button"
320-
className="inline-flex w-full items-center justify-center rounded-md border border-white/20 px-2 py-1 text-sm font-medium text-white transition hover:border-indigo-400 hover:text-indigo-200"
354+
className="inline-flex w-full items-center justify-center rounded border border-white/20 px-2 py-1 text-sm font-medium text-white transition hover:border-indigo-400 hover:text-indigo-200"
321355
onClick={ () => toggleFlip( card._id, false ) }
322356
>
323357
Show Card Front
@@ -337,7 +371,7 @@ const GridView = ( { aggregatedData, onDeleteCard, onUpdateCard } ) => {
337371
onChange={ ( event ) => handleChange( event, card._id, "quantity" ) }
338372
onBlur={ () => handleSave( card._id, "quantity" ) }
339373
onKeyDown={ handleQuantityKeyDown }
340-
className="min-w-[4rem] rounded-lg border border-white/30 bg-black/60 px-3 py-1 text-center text-white focus:border-indigo-400 focus:outline-none focus:ring-2 focus:ring-indigo-400/60"
374+
className="min-w-[4rem] rounded border border-white/30 bg-black/60 px-3 py-1 text-center text-white focus:border-indigo-400 focus:outline-none focus:ring-2 focus:ring-indigo-400/60"
341375
min={ 0 }
342376
/>
343377
) : (
@@ -355,7 +389,7 @@ const GridView = ( { aggregatedData, onDeleteCard, onUpdateCard } ) => {
355389
<span className="text-xs font-semibold uppercase tracking-wide text-rose-300">Remove Amount</span>
356390
{ edit[ card._id ] === "deleteAmount" ? (
357391
<input
358-
className="min-w-[4rem] rounded-lg border border-rose-300/60 bg-black/60 px-3 py-1 text-center text-white focus:border-rose-400 focus:outline-none focus:ring-2 focus:ring-rose-400/60"
392+
className="min-w-[4rem] rounded border border-rose-300/60 bg-black/60 px-3 py-1 text-center text-white focus:border-rose-400 focus:outline-none focus:ring-2 focus:ring-rose-400/60"
359393
type="number"
360394
min={ 0 }
361395
max={ Math.max( quantity, 0 ) }

components/Yugioh/TableView.js

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ const normalizeValue = ( value, type ) => {
2323
return ( value ?? '' ).toString().toLowerCase();
2424
};
2525

26-
const TableView = ( { aggregatedData = [], onDeleteCard, onUpdateCard } ) => {
26+
const TableView = ( { aggregatedData = [], onDeleteCard, onUpdateCard, sortConfig, handleSortChange } ) => {
2727
const safeCards = Array.isArray( aggregatedData ) ? aggregatedData : [];
28-
const [ sortConfig, setSortConfig ] = useState( { key: DEFAULT_SORT_KEY, direction: 'ascending' } );
28+
const isExternallySorted = Boolean( sortConfig && typeof handleSortChange === 'function' );
29+
const [ internalSortConfig, setInternalSortConfig ] = useState( { key: DEFAULT_SORT_KEY, direction: 'ascending' } );
30+
const activeSortConfig = isExternallySorted ? sortConfig : internalSortConfig;
2931
const [ edit, setEdit ] = useState( {} );
3032
const [ editValues, setEditValues ] = useState( {} );
3133
const [ notification, setNotification ] = useState( { show: false, message: '' } );
@@ -142,16 +144,24 @@ const TableView = ( { aggregatedData = [], onDeleteCard, onUpdateCard } ) => {
142144

143145
const handleSort = ( key ) => {
144146
if ( !SORTABLE_COLUMNS[ key ] ) return;
147+
if ( isExternallySorted ) {
148+
handleSortChange( key );
149+
return;
150+
}
145151
let direction = 'ascending';
146-
if ( sortConfig.key === key && sortConfig.direction === 'ascending' ) {
152+
if ( activeSortConfig.key === key && activeSortConfig.direction === 'ascending' ) {
147153
direction = 'descending';
148154
}
149155

150-
setSortConfig( { key, direction } );
156+
setInternalSortConfig( { key, direction } );
151157
};
152158

153159
const sortedData = useMemo( () => {
154-
const { key, direction } = sortConfig;
160+
if ( isExternallySorted ) {
161+
return safeCards;
162+
}
163+
164+
const { key, direction } = activeSortConfig;
155165
const column = SORTABLE_COLUMNS[ key ] || SORTABLE_COLUMNS[ DEFAULT_SORT_KEY ];
156166
const items = [ ...safeCards ];
157167

@@ -164,11 +174,11 @@ const TableView = ( { aggregatedData = [], onDeleteCard, onUpdateCard } ) => {
164174
} );
165175

166176
return items;
167-
}, [ safeCards, sortConfig ] );
177+
}, [ activeSortConfig, isExternallySorted, safeCards ] );
168178

169179
const getSortArrow = ( key ) => {
170-
if ( sortConfig.key !== key ) return '';
171-
return sortConfig.direction === 'ascending' ? '^' : 'v';
180+
if ( activeSortConfig.key !== key ) return '';
181+
return activeSortConfig.direction === 'ascending' ? '^' : 'v';
172182
};
173183

174184
const displayedRowIds = useMemo(

constants/yugiohFilters.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export const YUGIOH_FILTER_SECTIONS = [
3131
},
3232
{
3333
id: "condition",
34-
label: "Condition",
34+
label: "Condition & Printing",
3535
options: [
3636
"Near Mint 1st Edition",
3737
"Lightly Played 1st Edition",
@@ -50,10 +50,5 @@ export const YUGIOH_FILTER_SECTIONS = [
5050
"Damaged Unlimited",
5151
],
5252
},
53-
{
54-
id: "printing",
55-
label: "Printing",
56-
options: ["1st Edition", "Unlimited", "Limited"],
57-
},
5853
];
5954

next.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/** @type {import('next').NextConfig} */
22
const nextConfig = {
33
reactStrictMode: true,
4-
productionBrowserSourceMaps: true,
4+
productionBrowserSourceMaps: false,
55

66
async headers() {
77
return [

0 commit comments

Comments
 (0)