@m3000/market 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/styles.css +2 -0
  2. package/dist/tokens.css +2 -0
  3. package/package.json +10 -10
  4. package/src/components/blocks/auction/Auction.tsx +0 -74
  5. package/src/components/blocks/auction/AuctionArtwork.tsx +0 -4
  6. package/src/components/blocks/auction/AuctionBidForm.tsx +0 -138
  7. package/src/components/blocks/auction/AuctionBidInput.tsx +0 -166
  8. package/src/components/blocks/auction/AuctionContext.tsx +0 -401
  9. package/src/components/blocks/auction/AuctionInfo.tsx +0 -36
  10. package/src/components/blocks/auction/AuctionLayout.tsx +0 -200
  11. package/src/components/blocks/auction/AuctionRankings.tsx +0 -435
  12. package/src/components/blocks/auction/AuctionStatusTag.tsx +0 -98
  13. package/src/components/blocks/auction/AuctionSuggestedBids.tsx +0 -203
  14. package/src/components/blocks/auction/AuctionYourBidCard.tsx +0 -125
  15. package/src/components/blocks/auction/AuctionYourBids.tsx +0 -61
  16. package/src/components/blocks/auction/index.ts +0 -42
  17. package/src/components/blocks/index.ts +0 -1
  18. package/src/components/index.ts +0 -2
  19. package/src/components/primitives/Button.tsx +0 -183
  20. package/src/components/primitives/Drawer.tsx +0 -125
  21. package/src/components/primitives/Feedback.tsx +0 -185
  22. package/src/components/primitives/MorphDialog.tsx +0 -160
  23. package/src/components/primitives/Price.tsx +0 -394
  24. package/src/components/primitives/PriceInput.tsx +0 -48
  25. package/src/components/primitives/Receipt.tsx +0 -711
  26. package/src/components/primitives/Scale.tsx +0 -287
  27. package/src/components/primitives/Separator.tsx +0 -87
  28. package/src/components/primitives/Skeleton.tsx +0 -33
  29. package/src/components/primitives/SteppedInput.tsx +0 -313
  30. package/src/components/primitives/Tabs.tsx +0 -161
  31. package/src/components/primitives/Tag.tsx +0 -48
  32. package/src/components/primitives/Text.tsx +0 -102
  33. package/src/components/primitives/countdown/Countdown.tsx +0 -43
  34. package/src/components/primitives/countdown/index.ts +0 -2
  35. package/src/components/primitives/framed-image/FramedImage.tsx +0 -51
  36. package/src/components/primitives/framed-image/index.ts +0 -1
  37. package/src/components/primitives/index.ts +0 -42
  38. package/src/components/primitives/ranked-list/RankedList.tsx +0 -9
  39. package/src/components/primitives/ranked-list/Ranking.tsx +0 -454
  40. package/src/components/primitives/ranked-list/index.ts +0 -8
  41. package/src/hooks/index.ts +0 -1
  42. package/src/hooks/useCountdown.ts +0 -91
  43. package/src/index.ts +0 -130
  44. package/src/lib/cn.ts +0 -81
  45. package/src/lib/index.ts +0 -2
  46. package/src/lib/motion.ts +0 -55
  47. package/src/public/lea-83-time-walk.png +0 -0
  48. package/src/public/lea-83-time-walk.webp +0 -0
  49. package/src/stories/Auction.stories.tsx +0 -658
  50. package/src/stories/AuctionLayout.stories.tsx +0 -313
  51. package/src/stories/AuctionStatusTag.stories.tsx +0 -166
  52. package/src/stories/AuctionYourBidCard.stories.tsx +0 -257
  53. package/src/stories/Button.stories.tsx +0 -306
  54. package/src/stories/Countdown.stories.tsx +0 -158
  55. package/src/stories/Feedback.stories.tsx +0 -80
  56. package/src/stories/FramedImage.stories.tsx +0 -46
  57. package/src/stories/MorphDialog.stories.tsx +0 -88
  58. package/src/stories/Price.stories.tsx +0 -292
  59. package/src/stories/RankedList.stories.tsx +0 -190
  60. package/src/stories/Receipt.stories.tsx +0 -221
  61. package/src/stories/Scale.stories.tsx +0 -578
  62. package/src/stories/Separator.stories.tsx +0 -188
  63. package/src/stories/Skeleton.stories.tsx +0 -138
  64. package/src/stories/SteppedInput.stories.tsx +0 -321
  65. package/src/stories/Tabs.stories.tsx +0 -215
  66. package/src/stories/Tag.stories.tsx +0 -138
  67. package/src/stories/Text.stories.tsx +0 -245
  68. package/src/styles/globals.css +0 -39
  69. package/src/styles/index.css +0 -4
  70. package/src/styles/theme/animation.css +0 -11
  71. package/src/styles/theme/color.css +0 -185
  72. package/src/styles/theme/index.css +0 -3
  73. package/src/styles/theme/typography.css +0 -3
  74. package/src/styles/utility.css +0 -8
  75. package/src/types/index.ts +0 -149
  76. package/src/utils/format.ts +0 -130
  77. package/src/utils/index.ts +0 -16
  78. package/src/utils/rank-utils.ts +0 -131
  79. package/src/utils/tick-validation.ts +0 -65
@@ -1,401 +0,0 @@
1
- "use client";
2
-
3
- import {
4
- createContext,
5
- useCallback,
6
- useContext,
7
- useMemo,
8
- useState,
9
- } from "react";
10
- import type {
11
- AuctionData,
12
- AuctionFormatters,
13
- AuctionTickConfig,
14
- AuctionUserBid,
15
- OperationState,
16
- RankableBid,
17
- } from "@/types";
18
- import { getProjectedRankForPrice, getSuggestedBidPrices } from "@/utils";
19
-
20
- export interface AuctionContextValue {
21
- auction: AuctionData;
22
- isAuctionEnded: boolean;
23
-
24
- bids: RankableBid[];
25
- userBids: AuctionUserBid[];
26
- maxTotalItems: number;
27
-
28
- bidValue: bigint;
29
- setBidValue: (value: bigint | ((prev: bigint) => bigint)) => void;
30
-
31
- minBidValue: bigint;
32
- reservePriceValue: bigint;
33
- tickReferencePrice: bigint;
34
- tickConfig: AuctionTickConfig | undefined;
35
- tickSize: bigint;
36
-
37
- placeBidOperation: OperationState;
38
- topUpOperation: OperationState;
39
-
40
- lockedBid: { bidId: bigint; priceValue: bigint } | null;
41
-
42
- mergedForRank: RankableBid[];
43
- getRankForBid: (bidId: string) => number | null;
44
- getProjectedRank: (priceValue: bigint) => {
45
- rank: number | null;
46
- isWinning: boolean;
47
- };
48
- getSuggestedBids: () => bigint[];
49
-
50
- showBidPreview: boolean;
51
- setShowBidPreview: (show: boolean) => void;
52
-
53
- isBiddingActive: boolean;
54
- setIsBiddingActive: (active: boolean) => void;
55
- startBidding: () => void;
56
- cancelBidding: () => void;
57
-
58
- setLockedBid: (bid: { bidId: bigint; priceValue: bigint } | null) => void;
59
- handlePlaceBid: (price: string) => Promise<boolean>;
60
- handleTopUp: (newPrice: string) => Promise<boolean>;
61
- handleClaimEdition?: (bidId: string) => Promise<boolean>;
62
- resetOperations: () => void;
63
-
64
- formatPrice: (priceValue: bigint) => string;
65
- formatTime: (date: Date) => string;
66
- currencySymbol: string;
67
- inputDecimals: number;
68
- }
69
-
70
- export const AuctionContext: React.Context<AuctionContextValue | null> =
71
- createContext<AuctionContextValue | null>(null);
72
-
73
- export function useAuctionContext(): AuctionContextValue {
74
- const ctx = useContext(AuctionContext);
75
- if (!ctx) {
76
- throw new Error(
77
- "useAuctionContext must be used within an Auction provider",
78
- );
79
- }
80
- return ctx;
81
- }
82
-
83
- export interface AuctionProviderProps {
84
- auction: AuctionData;
85
- bids: RankableBid[];
86
- userBids: AuctionUserBid[];
87
- onPlaceBid: (price: bigint, quantity: bigint) => Promise<boolean>;
88
- onTopUpBid: (
89
- bidId: bigint,
90
- newPrice: bigint,
91
- additionalValue: bigint,
92
- ) => Promise<boolean>;
93
- onClaimEdition?: (bidId: string) => Promise<boolean>;
94
- formatters?: AuctionFormatters;
95
- children: React.ReactNode;
96
- }
97
-
98
- export function AuctionProvider({
99
- auction,
100
- bids,
101
- userBids,
102
- onPlaceBid,
103
- onTopUpBid,
104
- onClaimEdition,
105
- formatters,
106
- children,
107
- }: AuctionProviderProps): React.ReactElement {
108
- const defaultFormatPrice = (priceValue: bigint) => {
109
- const val = Number(priceValue) / 1e18;
110
- return val.toLocaleString("en-US", {
111
- minimumFractionDigits: 3,
112
- maximumFractionDigits: 3,
113
- });
114
- };
115
- const defaultFormatTime = (date: Date) => {
116
- const now = Date.now();
117
- const diff = date.getTime() - now;
118
- const isPast = diff < 0;
119
- const absMs = Math.abs(diff);
120
- const seconds = Math.floor(absMs / 1000);
121
- const minutes = Math.floor(seconds / 60);
122
- const hours = Math.floor(minutes / 60);
123
- const days = Math.floor(hours / 24);
124
-
125
- if (days > 0) return `${days}d ${hours % 24}h ${isPast ? "ago" : ""}`;
126
- if (hours > 0) return `${hours}h ${minutes % 60}m ${isPast ? "ago" : ""}`;
127
- if (minutes > 0)
128
- return `${minutes}m ${seconds % 60}s ${isPast ? "ago" : ""}`;
129
- return `${seconds}s ${isPast ? "ago" : ""}`;
130
- };
131
-
132
- const formatPrice = formatters?.formatPrice ?? defaultFormatPrice;
133
- const formatTime = formatters?.formatTime ?? defaultFormatTime;
134
- const currencySymbol = formatters?.currencySymbol ?? "USD";
135
- const inputDecimals = formatters?.inputDecimals ?? 18;
136
-
137
- const isAuctionEnded = auction.endsAt
138
- ? Date.now() > auction.endsAt.getTime()
139
- : false;
140
-
141
- const reservePriceValue = auction.reservePrice;
142
- const tickConfig = auction.tickConfig;
143
-
144
- const activeBids = bids.filter((b) => {
145
- const bid = userBids.find((ub) => ub.id === b.id);
146
- return !bid || bid.status === "active";
147
- });
148
-
149
- const totalActiveQty = BigInt(activeBids.length);
150
-
151
- const mergedForRank = useMemo(() => {
152
- const cutoffIds = new Set(bids.map((b) => b.id));
153
-
154
- const myActiveBids = userBids.filter(
155
- (bid) => bid.status === "active" && !cutoffIds.has(bid.id),
156
- );
157
-
158
- const myBidsNotInCutoff: RankableBid[] = myActiveBids.map((bid) => ({
159
- id: bid.id,
160
- price: bid.price.toString(),
161
- created_at: bid.createdAt.toISOString(),
162
- }));
163
-
164
- const merged: RankableBid[] = [...bids, ...myBidsNotInCutoff];
165
-
166
- return merged.sort((a, b) => {
167
- const pa = BigInt(a.price);
168
- const pb = BigInt(b.price);
169
- if (pa !== pb) return pb > pa ? 1 : -1;
170
- return (
171
- new Date(a.created_at).getTime() - new Date(b.created_at).getTime()
172
- );
173
- });
174
- }, [bids, userBids]);
175
-
176
- const minBidValue = useMemo(() => {
177
- if (totalActiveQty >= BigInt(auction.maxTotalItems)) {
178
- const winningBids = mergedForRank.slice(0, auction.maxTotalItems);
179
-
180
- if (winningBids.length > 0) {
181
- const lastWinning = winningBids[winningBids.length - 1];
182
- const tickSize = tickConfig
183
- ? BigInt(lastWinning.price) > tickConfig.threshold
184
- ? tickConfig.largeTickSize
185
- : tickConfig.smallTickSize
186
- : BigInt(lastWinning.price);
187
- return BigInt(lastWinning.price) + tickSize;
188
- }
189
- }
190
- return reservePriceValue;
191
- }, [
192
- reservePriceValue,
193
- totalActiveQty,
194
- auction.maxTotalItems,
195
- mergedForRank,
196
- tickConfig,
197
- ]);
198
-
199
- const tickReferencePrice = minBidValue;
200
-
201
- const tickSize = useMemo(() => {
202
- if (!tickConfig) return minBidValue;
203
- return BigInt(minBidValue) > tickConfig.threshold
204
- ? tickConfig.largeTickSize
205
- : tickConfig.smallTickSize;
206
- }, [tickConfig, minBidValue]);
207
-
208
- const getRankForBid = useCallback(
209
- (bidId: string) => {
210
- const idx = mergedForRank.findIndex((b) => b.id === bidId);
211
- return idx >= 0 ? idx + 1 : null;
212
- },
213
- [mergedForRank],
214
- );
215
-
216
- const getProjectedRank = useCallback(
217
- (priceValue: bigint) => {
218
- return getProjectedRankForPrice(
219
- priceValue,
220
- mergedForRank,
221
- auction.maxTotalItems,
222
- );
223
- },
224
- [mergedForRank, auction.maxTotalItems],
225
- );
226
-
227
- const getSuggestedBids = useCallback(() => {
228
- return getSuggestedBidPrices({
229
- mergedForRank,
230
- maxTotalItems: auction.maxTotalItems,
231
- minBidValue,
232
- reservePriceValue,
233
- tickConfig,
234
- tickSize,
235
- });
236
- }, [
237
- mergedForRank,
238
- auction.maxTotalItems,
239
- minBidValue,
240
- reservePriceValue,
241
- tickConfig,
242
- tickSize,
243
- ]);
244
-
245
- const [placeBidOperation, setPlaceBidOperation] = useState<OperationState>({
246
- status: "idle",
247
- });
248
- const [topUpOperation, setTopUpOperation] = useState<OperationState>({
249
- status: "idle",
250
- });
251
-
252
- const [lockedBid, setLockedBid] = useState<{
253
- bidId: bigint;
254
- priceValue: bigint;
255
- } | null>(null);
256
-
257
- const [showBidPreview, setShowBidPreview] = useState(false);
258
-
259
- const [isBiddingActive, setIsBiddingActive] = useState(false);
260
-
261
- const startBidding = useCallback(() => {
262
- setIsBiddingActive(true);
263
- setShowBidPreview(true);
264
- }, []);
265
-
266
- const cancelBidding = useCallback(() => {
267
- setIsBiddingActive(false);
268
- setShowBidPreview(false);
269
- setLockedBid(null);
270
- }, []);
271
-
272
- const setLockedBidAndActivate = useCallback(
273
- (bid: { bidId: bigint; priceValue: bigint } | null) => {
274
- setLockedBid(bid);
275
- if (bid !== null) {
276
- setIsBiddingActive(true);
277
- setShowBidPreview(true);
278
- }
279
- },
280
- [],
281
- );
282
-
283
- const [bidValue, setBidValue] = useState<bigint>(minBidValue);
284
-
285
- const resetOperations = useCallback(() => {
286
- setPlaceBidOperation({ status: "idle" });
287
- setTopUpOperation({ status: "idle" });
288
- }, []);
289
-
290
- const handlePlaceBid = useCallback(
291
- async (price: string) => {
292
- const priceValue = BigInt(price);
293
- setPlaceBidOperation({ status: "pending" });
294
-
295
- try {
296
- const success = await onPlaceBid(priceValue, 1n);
297
- if (success) {
298
- setPlaceBidOperation({ status: "success" });
299
- setShowBidPreview(false);
300
- return true;
301
- } else {
302
- setPlaceBidOperation({
303
- status: "error",
304
- error: "Transaction failed",
305
- });
306
- return false;
307
- }
308
- } catch (err) {
309
- setPlaceBidOperation({
310
- status: "error",
311
- error: err instanceof Error ? err.message : "Unknown error",
312
- });
313
- return false;
314
- }
315
- },
316
- [onPlaceBid],
317
- );
318
-
319
- const handleTopUp = useCallback(
320
- async (newPrice: string) => {
321
- if (!lockedBid) return false;
322
-
323
- const newPriceValue = BigInt(newPrice);
324
- const additionalValue = newPriceValue - lockedBid.priceValue;
325
-
326
- setTopUpOperation({ status: "pending" });
327
-
328
- try {
329
- const success = await onTopUpBid(
330
- lockedBid.bidId,
331
- newPriceValue,
332
- additionalValue,
333
- );
334
- if (success) {
335
- setTopUpOperation({ status: "success" });
336
- setLockedBid(null);
337
- return true;
338
- } else {
339
- setTopUpOperation({ status: "error", error: "Transaction failed" });
340
- return false;
341
- }
342
- } catch (err) {
343
- setTopUpOperation({
344
- status: "error",
345
- error: err instanceof Error ? err.message : "Unknown error",
346
- });
347
- return false;
348
- }
349
- },
350
- [lockedBid, onTopUpBid],
351
- );
352
-
353
- const handleClaimEdition = useCallback(
354
- async (bidId: string) => {
355
- if (!onClaimEdition) return false;
356
- return onClaimEdition(bidId);
357
- },
358
- [onClaimEdition],
359
- );
360
-
361
- const value: AuctionContextValue = {
362
- auction,
363
- isAuctionEnded,
364
- bids,
365
- userBids,
366
- maxTotalItems: auction.maxTotalItems,
367
- bidValue,
368
- setBidValue,
369
- minBidValue,
370
- reservePriceValue,
371
- tickReferencePrice,
372
- tickConfig,
373
- tickSize,
374
- placeBidOperation,
375
- topUpOperation,
376
- lockedBid,
377
- mergedForRank,
378
- getRankForBid,
379
- getProjectedRank,
380
- getSuggestedBids,
381
- showBidPreview,
382
- setShowBidPreview,
383
- isBiddingActive,
384
- setIsBiddingActive,
385
- startBidding,
386
- cancelBidding,
387
- setLockedBid: setLockedBidAndActivate,
388
- handlePlaceBid,
389
- handleTopUp,
390
- handleClaimEdition,
391
- resetOperations,
392
- formatPrice,
393
- formatTime,
394
- currencySymbol,
395
- inputDecimals,
396
- };
397
-
398
- return (
399
- <AuctionContext.Provider value={value}>{children}</AuctionContext.Provider>
400
- );
401
- }
@@ -1,36 +0,0 @@
1
- "use client";
2
-
3
- import { Text } from "@/components/primitives";
4
- import { useAuctionContext } from "./AuctionContext";
5
- import { AuctionStatusTag } from "./AuctionStatusTag";
6
-
7
- export interface AuctionInfoProps {
8
- className?: string;
9
- }
10
-
11
- export function AuctionInfo({
12
- className,
13
- }: AuctionInfoProps): React.ReactElement {
14
- const { auction, isAuctionEnded, maxTotalItems } = useAuctionContext();
15
-
16
- const editionsLabel =
17
- maxTotalItems === 1 ? "1 item" : `${maxTotalItems} items`;
18
-
19
- return (
20
- <div className={className}>
21
- <div className="flex flex-wrap items-center gap-2">
22
- <AuctionStatusTag
23
- opensAt={auction.opensAt}
24
- endsAt={auction.endsAt}
25
- background="transparent"
26
- />
27
- </div>
28
- {!isAuctionEnded ? (
29
- <Text size="2" color="tertiary" className="mt-2">
30
- Bid on one of {editionsLabel}. Top {maxTotalItems} bidders win and pay
31
- the lowest winning bid.
32
- </Text>
33
- ) : null}
34
- </div>
35
- );
36
- }
@@ -1,200 +0,0 @@
1
- "use client";
2
-
3
- import type { ReactNode } from "react";
4
- import { Button } from "@/components/primitives";
5
- import { cn } from "@/lib";
6
- import { useAuctionContext } from "./AuctionContext";
7
-
8
- export interface AuctionLayoutProps {
9
- children: ReactNode;
10
- className?: string;
11
- height?: string | number;
12
- }
13
-
14
- export function AuctionLayout({
15
- children,
16
- className,
17
- height = "calc(100vh - 4rem)",
18
- }: AuctionLayoutProps): React.ReactElement {
19
- const heightStyle = typeof height === "number" ? `${height}px` : height;
20
- const { isBiddingActive } = useAuctionContext();
21
-
22
- return (
23
- <div
24
- className={cn(
25
- "relative grid overflow-hidden grid-rows-[minmax(0,1fr)_minmax(0,1fr)]",
26
- isBiddingActive && "grid-rows-1",
27
- "lg:grid-cols-2 lg:grid-rows-1",
28
- className,
29
- )}
30
- style={{ height: heightStyle }}
31
- >
32
- {children}
33
- </div>
34
- );
35
- }
36
-
37
- export interface AuctionDetailsProps {
38
- children: ReactNode;
39
- className?: string;
40
- }
41
-
42
- export function AuctionDetails({
43
- children,
44
- className,
45
- }: AuctionDetailsProps): React.ReactElement {
46
- const { isBiddingActive } = useAuctionContext();
47
-
48
- return (
49
- <div
50
- className={cn(
51
- "relative flex h-full min-h-0 flex-col overflow-hidden",
52
- "border-border",
53
- "lg:border-r",
54
- isBiddingActive && "overflow-hidden",
55
- className,
56
- )}
57
- >
58
- {children}
59
- </div>
60
- );
61
- }
62
-
63
- export interface AuctionDetailsHeaderProps {
64
- children: ReactNode;
65
- className?: string;
66
- }
67
-
68
- export function AuctionDetailsHeader({
69
- children,
70
- className,
71
- }: AuctionDetailsHeaderProps): React.ReactElement {
72
- const { isBiddingActive } = useAuctionContext();
73
-
74
- return (
75
- <div
76
- className={cn(
77
- "flex min-h-0 grow flex-col p-6",
78
- isBiddingActive &&
79
- [
80
- "max-lg:overflow-hidden",
81
- "max-lg:[&>*:nth-child(n+3):not(:last-child)]:hidden",
82
- "max-lg:[&>*:last-child]:pointer-events-none",
83
- "max-lg:[&>*:last-child]:absolute",
84
- "max-lg:[&>*:last-child]:inset-x-6",
85
- "max-lg:[&>*:last-child]:bottom-6",
86
- "max-lg:[&>*:last-child]:top-28",
87
- "max-lg:[&>*:last-child]:min-h-0",
88
- "max-lg:[&>*:last-child]:overflow-hidden",
89
- ].join(" "),
90
- className,
91
- )}
92
- >
93
- {children}
94
- </div>
95
- );
96
- }
97
-
98
- export interface AuctionDetailsBodyProps {
99
- children: ReactNode;
100
- className?: string;
101
- }
102
-
103
- export function AuctionDetailsBody({
104
- children,
105
- className,
106
- }: AuctionDetailsBodyProps): React.ReactElement {
107
- return (
108
- <div
109
- className={cn(
110
- "hidden p-6 lg:block lg:min-h-0 lg:flex-1 lg:overflow-y-auto",
111
- className,
112
- )}
113
- >
114
- {children}
115
- </div>
116
- );
117
- }
118
-
119
- export interface AuctionDetailsFooterProps {
120
- children: ReactNode;
121
- className?: string;
122
- }
123
-
124
- export function AuctionDetailsFooter({
125
- children,
126
- className,
127
- }: AuctionDetailsFooterProps): React.ReactElement {
128
- return (
129
- <div
130
- className={cn("mt-auto shrink-0 border-t border-border p-6", className)}
131
- >
132
- {children}
133
- </div>
134
- );
135
- }
136
-
137
- export interface AuctionRankingsContainerProps {
138
- children: ReactNode;
139
- className?: string;
140
- }
141
-
142
- export function AuctionRankingsContainer({
143
- children,
144
- className,
145
- }: AuctionRankingsContainerProps): React.ReactElement {
146
- const { isBiddingActive } = useAuctionContext();
147
-
148
- return (
149
- <div
150
- className={cn(
151
- "grid h-full min-h-0 grid-rows-[minmax(0,1fr)_auto]",
152
- isBiddingActive &&
153
- "max-lg:absolute max-lg:inset-x-0 max-lg:bottom-0 max-lg:top-0 max-lg:z-20 max-lg:overflow-hidden max-lg:rounded-t-[1.75rem] max-lg:border-t max-lg:border-border max-lg:bg-background/95 max-lg:shadow-2xl max-lg:backdrop-blur-sm",
154
- className,
155
- )}
156
- >
157
- {children}
158
- </div>
159
- );
160
- }
161
-
162
- export interface AuctionBiddingPanelProps {
163
- children: ReactNode;
164
- className?: string;
165
- }
166
-
167
- export function AuctionBiddingPanel({
168
- children,
169
- className,
170
- }: AuctionBiddingPanelProps): React.ReactElement {
171
- const { isBiddingActive, startBidding, isAuctionEnded, setShowBidPreview } =
172
- useAuctionContext();
173
-
174
- const handleStartBidding = () => {
175
- startBidding();
176
- setShowBidPreview(true);
177
- };
178
-
179
- return (
180
- <div
181
- className={cn(
182
- "row-start-2 rounded-t-[1.75rem] border-t border-border bg-background p-6 lg:rounded-xl",
183
- className,
184
- )}
185
- >
186
- {!isBiddingActive ? (
187
- <Button
188
- className="w-full"
189
- size="lg"
190
- disabled={isAuctionEnded}
191
- onClick={handleStartBidding}
192
- >
193
- {isAuctionEnded ? "Auction Ended" : "Start Bidding"}
194
- </Button>
195
- ) : (
196
- children
197
- )}
198
- </div>
199
- );
200
- }