@pradip1995/segment-powerhouse-cart 0.1.1 → 0.1.3
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.
- package/package.json +3 -2
- package/src/cart.css +153 -0
- package/src/segment.tsx +104 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pradip1995/segment-powerhouse-cart",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -26,7 +26,8 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@pradip1995/segment-analytics": "^0.2.4",
|
|
29
|
-
"@pradip1995/segment-
|
|
29
|
+
"@pradip1995/segment-login-popup": "^0.1.3",
|
|
30
|
+
"@pradip1995/segment-primitives": "^0.4.11"
|
|
30
31
|
},
|
|
31
32
|
"devDependencies": {
|
|
32
33
|
"@medusajs/types": "^2.0.0",
|
package/src/cart.css
CHANGED
|
@@ -411,3 +411,156 @@
|
|
|
411
411
|
text-align: center;
|
|
412
412
|
}
|
|
413
413
|
}
|
|
414
|
+
|
|
415
|
+
@keyframes powerhouseModalFadeIn {
|
|
416
|
+
from {
|
|
417
|
+
opacity: 0;
|
|
418
|
+
transform: scale(0.95) translateY(10px);
|
|
419
|
+
}
|
|
420
|
+
to {
|
|
421
|
+
opacity: 1;
|
|
422
|
+
transform: scale(1) translateY(0);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
@keyframes powerhouseBackdropFade {
|
|
427
|
+
from { opacity: 0; }
|
|
428
|
+
to { opacity: 1; }
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.powerhouse-cart-confirm {
|
|
432
|
+
position: fixed;
|
|
433
|
+
inset: 0;
|
|
434
|
+
z-index: 99999;
|
|
435
|
+
display: flex;
|
|
436
|
+
align-items: center;
|
|
437
|
+
justify-content: center;
|
|
438
|
+
padding: 1.25rem;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
.powerhouse-cart-confirm__backdrop {
|
|
442
|
+
position: absolute;
|
|
443
|
+
inset: 0;
|
|
444
|
+
border: 0;
|
|
445
|
+
background: rgba(15, 10, 25, 0.55);
|
|
446
|
+
backdrop-filter: blur(6px);
|
|
447
|
+
-webkit-backdrop-filter: blur(6px);
|
|
448
|
+
animation: powerhouseBackdropFade 0.2s ease-out forwards;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.powerhouse-cart-confirm__panel {
|
|
452
|
+
position: relative;
|
|
453
|
+
width: min(25.5rem, 100%);
|
|
454
|
+
padding: 2.25rem 2rem 1.75rem;
|
|
455
|
+
background: #ffffff;
|
|
456
|
+
border-radius: 1.25rem;
|
|
457
|
+
border: 1px solid rgba(59, 31, 78, 0.1);
|
|
458
|
+
box-shadow:
|
|
459
|
+
0 20px 40px -10px rgba(30, 15, 45, 0.25),
|
|
460
|
+
0 2px 10px rgba(0, 0, 0, 0.05);
|
|
461
|
+
text-align: center;
|
|
462
|
+
animation: powerhouseModalFadeIn 0.25s cubic-bezier(0.16, 1, 0.3, 1) forwards;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
.powerhouse-cart-confirm__close {
|
|
466
|
+
position: absolute;
|
|
467
|
+
top: 1rem;
|
|
468
|
+
right: 1rem;
|
|
469
|
+
display: flex;
|
|
470
|
+
align-items: center;
|
|
471
|
+
justify-content: center;
|
|
472
|
+
width: 2rem;
|
|
473
|
+
height: 2rem;
|
|
474
|
+
padding: 0;
|
|
475
|
+
border: none;
|
|
476
|
+
border-radius: 9999px;
|
|
477
|
+
background: rgba(59, 31, 78, 0.05);
|
|
478
|
+
color: #6b7280;
|
|
479
|
+
font-size: 0.875rem;
|
|
480
|
+
line-height: 1;
|
|
481
|
+
cursor: pointer;
|
|
482
|
+
transition: all 0.2s ease;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
.powerhouse-cart-confirm__close:hover {
|
|
486
|
+
background: rgba(59, 31, 78, 0.12);
|
|
487
|
+
color: #111827;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
.powerhouse-cart-confirm__title {
|
|
491
|
+
margin: 0 0 0.5rem;
|
|
492
|
+
font-family: var(--font-heading, Georgia, serif);
|
|
493
|
+
font-size: 1.4rem;
|
|
494
|
+
font-weight: 500;
|
|
495
|
+
letter-spacing: -0.01em;
|
|
496
|
+
color: #111827;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
.powerhouse-cart-confirm__text {
|
|
500
|
+
margin: 0 0 1.5rem;
|
|
501
|
+
font-size: 0.875rem;
|
|
502
|
+
line-height: 1.5;
|
|
503
|
+
color: #4b5563;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
.powerhouse-cart-confirm__actions {
|
|
507
|
+
display: flex;
|
|
508
|
+
flex-direction: column;
|
|
509
|
+
gap: 0.625rem;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
.powerhouse-cart-confirm__btn {
|
|
513
|
+
display: inline-flex;
|
|
514
|
+
align-items: center;
|
|
515
|
+
justify-content: center;
|
|
516
|
+
min-height: 2.75rem;
|
|
517
|
+
padding: 0.7rem 1.25rem;
|
|
518
|
+
border-radius: 9999px;
|
|
519
|
+
font-size: 0.75rem;
|
|
520
|
+
font-weight: 600;
|
|
521
|
+
letter-spacing: 0.09em;
|
|
522
|
+
text-transform: uppercase;
|
|
523
|
+
cursor: pointer;
|
|
524
|
+
transition: all 0.2s ease;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
.powerhouse-cart-confirm__btn--primary {
|
|
528
|
+
border: 1px solid #362447;
|
|
529
|
+
background: #362447;
|
|
530
|
+
color: #ffffff;
|
|
531
|
+
box-shadow: 0 4px 14px rgba(54, 36, 71, 0.25);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
.powerhouse-cart-confirm__btn--primary:hover:not(:disabled) {
|
|
535
|
+
background: #4a3260;
|
|
536
|
+
border-color: #4a3260;
|
|
537
|
+
box-shadow: 0 6px 18px rgba(54, 36, 71, 0.35);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
.powerhouse-cart-confirm__btn--danger {
|
|
541
|
+
border: 1px solid #dc2626;
|
|
542
|
+
background: #ffffff;
|
|
543
|
+
color: #dc2626;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
.powerhouse-cart-confirm__btn--danger:hover:not(:disabled) {
|
|
547
|
+
background: #fef2f2;
|
|
548
|
+
border-color: #b91c1c;
|
|
549
|
+
color: #b91c1c;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
.powerhouse-cart-confirm__btn--ghost {
|
|
553
|
+
border: 1px solid transparent;
|
|
554
|
+
background: transparent;
|
|
555
|
+
color: #6b7280;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
.powerhouse-cart-confirm__btn--ghost:hover:not(:disabled) {
|
|
559
|
+
background: rgba(59, 31, 78, 0.05);
|
|
560
|
+
color: #111827;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
.powerhouse-cart-confirm__btn:disabled {
|
|
564
|
+
opacity: 0.75;
|
|
565
|
+
cursor: not-allowed;
|
|
566
|
+
}
|
package/src/segment.tsx
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
import Image from "next/image"
|
|
4
4
|
import { useRouter } from "next/navigation"
|
|
5
|
-
import { useTransition } from "react"
|
|
5
|
+
import { useEffect, useState, useTransition } from "react"
|
|
6
|
+
import { createPortal } from "react-dom"
|
|
6
7
|
import type { HttpTypes } from "@medusajs/types"
|
|
7
8
|
import { deleteLineItem, updateLineItem } from "@pradip1995/commerce-core/client/actions/cart"
|
|
9
|
+
import { addToWishlist } from "@pradip1995/commerce-core/client/actions/wishlist"
|
|
8
10
|
import {
|
|
9
11
|
trackCartLineItemQuantityChange,
|
|
10
12
|
trackCartLineItemRemoved,
|
|
@@ -12,6 +14,7 @@ import {
|
|
|
12
14
|
import LocalizedLink from "@pradip1995/segment-primitives/localized-link"
|
|
13
15
|
import { formatPrice } from "@pradip1995/segment-primitives/format-price"
|
|
14
16
|
import { resolveMediaUrl } from "@pradip1995/segment-primitives/resolve-media-url"
|
|
17
|
+
import LoginRequiredModal from "@pradip1995/segment-login-popup/required"
|
|
15
18
|
import {
|
|
16
19
|
DEFAULT_CHECKOUT_LABEL,
|
|
17
20
|
DEFAULT_CONTINUE_HREF,
|
|
@@ -131,10 +134,17 @@ function LineItemRow({
|
|
|
131
134
|
}) {
|
|
132
135
|
const router = useRouter()
|
|
133
136
|
const [pending, startTransition] = useTransition()
|
|
137
|
+
const [confirmOpen, setConfirmOpen] = useState(false)
|
|
138
|
+
const [loginRequired, setLoginRequired] = useState(false)
|
|
139
|
+
const [mounted, setMounted] = useState(false)
|
|
134
140
|
const thumbnail = lineItemImage(item)
|
|
135
141
|
const variantLabel = item.variant?.title
|
|
136
142
|
const showVariant = Boolean(variantLabel && !isPlaceholderVariant(variantLabel))
|
|
137
143
|
|
|
144
|
+
useEffect(() => {
|
|
145
|
+
setMounted(true)
|
|
146
|
+
}, [])
|
|
147
|
+
|
|
138
148
|
function changeQty(next: number) {
|
|
139
149
|
if (next < 1 || !item.id) return
|
|
140
150
|
const previousQuantity = item.quantity ?? 1
|
|
@@ -145,11 +155,36 @@ function LineItemRow({
|
|
|
145
155
|
})
|
|
146
156
|
}
|
|
147
157
|
|
|
148
|
-
function
|
|
158
|
+
function removeFromCart() {
|
|
149
159
|
if (!item.id) return
|
|
150
160
|
startTransition(async () => {
|
|
151
161
|
trackCartLineItemRemoved(item, currency)
|
|
152
162
|
await deleteLineItem(item.id)
|
|
163
|
+
setConfirmOpen(false)
|
|
164
|
+
router.refresh()
|
|
165
|
+
})
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function moveToWishlist() {
|
|
169
|
+
const productId = item.product_id
|
|
170
|
+
if (!productId) {
|
|
171
|
+
removeFromCart()
|
|
172
|
+
return
|
|
173
|
+
}
|
|
174
|
+
startTransition(async () => {
|
|
175
|
+
const result = await addToWishlist(productId)
|
|
176
|
+
if (!result.success && result.error?.toLowerCase().includes("login")) {
|
|
177
|
+
setConfirmOpen(false)
|
|
178
|
+
setLoginRequired(true)
|
|
179
|
+
return
|
|
180
|
+
}
|
|
181
|
+
if (!result.success) {
|
|
182
|
+
setConfirmOpen(false)
|
|
183
|
+
return
|
|
184
|
+
}
|
|
185
|
+
trackCartLineItemRemoved(item, currency)
|
|
186
|
+
if (item.id) await deleteLineItem(item.id)
|
|
187
|
+
setConfirmOpen(false)
|
|
153
188
|
router.refresh()
|
|
154
189
|
})
|
|
155
190
|
}
|
|
@@ -201,11 +236,77 @@ function LineItemRow({
|
|
|
201
236
|
+
|
|
202
237
|
</button>
|
|
203
238
|
</div>
|
|
204
|
-
<button
|
|
239
|
+
<button
|
|
240
|
+
type="button"
|
|
241
|
+
className="powerhouse-cart__remove"
|
|
242
|
+
onClick={() => setConfirmOpen(true)}
|
|
243
|
+
disabled={pending}
|
|
244
|
+
>
|
|
205
245
|
Remove
|
|
206
246
|
</button>
|
|
207
247
|
</div>
|
|
208
248
|
<p className="powerhouse-cart__total">{formatPrice(lineTotal(item), currency)}</p>
|
|
249
|
+
|
|
250
|
+
{confirmOpen && mounted
|
|
251
|
+
? createPortal(
|
|
252
|
+
<div className="powerhouse-cart-confirm">
|
|
253
|
+
<button
|
|
254
|
+
type="button"
|
|
255
|
+
className="powerhouse-cart-confirm__backdrop"
|
|
256
|
+
aria-label="Close"
|
|
257
|
+
onClick={() => setConfirmOpen(false)}
|
|
258
|
+
/>
|
|
259
|
+
<div className="powerhouse-cart-confirm__panel" role="dialog" aria-modal="true">
|
|
260
|
+
<button
|
|
261
|
+
type="button"
|
|
262
|
+
className="powerhouse-cart-confirm__close"
|
|
263
|
+
aria-label="Close dialog"
|
|
264
|
+
onClick={() => setConfirmOpen(false)}
|
|
265
|
+
>
|
|
266
|
+
✕
|
|
267
|
+
</button>
|
|
268
|
+
<h3 className="powerhouse-cart-confirm__title">Remove this item?</h3>
|
|
269
|
+
<p className="powerhouse-cart-confirm__text">
|
|
270
|
+
Move it to your wishlist to save it for later, or remove it from your cart.
|
|
271
|
+
</p>
|
|
272
|
+
<div className="powerhouse-cart-confirm__actions">
|
|
273
|
+
<button
|
|
274
|
+
type="button"
|
|
275
|
+
className="powerhouse-cart-confirm__btn powerhouse-cart-confirm__btn--primary"
|
|
276
|
+
disabled={pending}
|
|
277
|
+
onClick={moveToWishlist}
|
|
278
|
+
>
|
|
279
|
+
{pending ? "Saving…" : "Move to Wishlist"}
|
|
280
|
+
</button>
|
|
281
|
+
<button
|
|
282
|
+
type="button"
|
|
283
|
+
className="powerhouse-cart-confirm__btn powerhouse-cart-confirm__btn--danger"
|
|
284
|
+
disabled={pending}
|
|
285
|
+
onClick={removeFromCart}
|
|
286
|
+
>
|
|
287
|
+
Remove the Product
|
|
288
|
+
</button>
|
|
289
|
+
<button
|
|
290
|
+
type="button"
|
|
291
|
+
className="powerhouse-cart-confirm__btn powerhouse-cart-confirm__btn--ghost"
|
|
292
|
+
disabled={pending}
|
|
293
|
+
onClick={() => setConfirmOpen(false)}
|
|
294
|
+
>
|
|
295
|
+
Keep in cart
|
|
296
|
+
</button>
|
|
297
|
+
</div>
|
|
298
|
+
</div>
|
|
299
|
+
</div>,
|
|
300
|
+
document.body
|
|
301
|
+
)
|
|
302
|
+
: null}
|
|
303
|
+
|
|
304
|
+
<LoginRequiredModal
|
|
305
|
+
isOpen={loginRequired}
|
|
306
|
+
onClose={() => setLoginRequired(false)}
|
|
307
|
+
countryCode={countryCode}
|
|
308
|
+
message="Please log in to move this item to your wishlist."
|
|
309
|
+
/>
|
|
209
310
|
</article>
|
|
210
311
|
)
|
|
211
312
|
}
|