@salifbiaye/create-boutique 0.1.4 → 0.2.0
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/cli/dist/commands.js +3 -3
- package/cli/dist/create.js +5 -5
- package/cli/dist/generate.js +68 -10
- package/cli/dist/project.js +2 -0
- package/cli/dist/themes.js +5 -1
- package/docs/guide-complet.en.html +11 -0
- package/docs/guide-complet.fr.html +11 -0
- package/package.json +1 -1
- package/templates/backend/src/lib/emails.ts +8 -1
- package/templates/backend/src/scripts/campaign-import.ts +6 -4
- package/templates/backend/src/scripts/seed.ts +15 -3
- package/templates/storefront/locales/en.json +40 -3
- package/templates/storefront/locales/fr.json +40 -3
- package/templates/storefront/package-lock.json +7 -0
- package/templates/storefront/package.json +1 -0
- package/templates/storefront/src/app/(main)/legal/[page]/page.tsx +3 -9
- package/templates/storefront/src/app/(main)/page.tsx +25 -0
- package/templates/storefront/src/app/(main)/store/page.tsx +3 -1
- package/templates/storefront/src/app/layout.tsx +9 -2
- package/templates/storefront/src/lib/boutique/config.ts +1 -0
- package/templates/storefront/src/lib/boutique/i18n-client.tsx +10 -2
- package/templates/storefront/src/lib/boutique/schema.ts +2 -0
- package/templates/storefront/src/lib/constants.tsx +5 -4
- package/templates/storefront/src/modules/account/components/account-nav/index.tsx +50 -177
- package/templates/storefront/src/modules/account/components/address-card/add-address.tsx +2 -2
- package/templates/storefront/src/modules/account/components/address-card/edit-address-modal.tsx +2 -2
- package/templates/storefront/src/modules/account/components/overview/index.tsx +98 -143
- package/templates/storefront/src/modules/account/components/profile-billing-address/index.tsx +2 -3
- package/templates/storefront/src/modules/account/components/profile-phone/index.tsx +2 -3
- package/templates/storefront/src/modules/account/components/register/index.tsx +2 -3
- package/templates/storefront/src/modules/account/templates/account-layout.tsx +20 -24
- package/templates/storefront/src/modules/checkout/components/billing_address/index.tsx +2 -2
- package/templates/storefront/src/modules/checkout/components/payment/index.tsx +2 -1
- package/templates/storefront/src/modules/checkout/components/payment-button/index.tsx +65 -48
- package/templates/storefront/src/modules/checkout/components/payment-container/index.tsx +23 -29
- package/templates/storefront/src/modules/checkout/components/payment-wrapper/stripe-wrapper.tsx +51 -6
- package/templates/storefront/src/modules/checkout/components/shipping-address/index.tsx +2 -2
- package/templates/storefront/src/modules/common/components/phone-input/index.tsx +110 -0
- package/templates/storefront/src/modules/store/templates/index.tsx +82 -17
- package/templates/storefront/src/modules/store/templates/paginated-products.tsx +5 -0
- package/templates/storefront/src/modules/ub/campaign-blocks.tsx +1 -1
- package/templates/storefront/src/modules/ub/contact-page.tsx +78 -0
- package/templates/storefront/src/modules/ub/footer.tsx +26 -5
- package/templates/storefront/src/modules/ub/mobile-menu.tsx +49 -0
- package/templates/storefront/src/modules/ub/nav.tsx +2 -0
- package/templates/storefront/src/modules/ub/showcase.tsx +137 -0
- package/templates/storefront/src/proxy.ts +3 -3
- package/templates/storefront/src/styles/ub/account.css +199 -0
- package/templates/storefront/src/styles/ub/black-friday.css +96 -0
- package/templates/storefront/src/styles/ub/forms.css +61 -0
- package/templates/storefront/src/styles/ub/pages.css +382 -0
- package/templates/storefront/src/styles/ub/responsive.css +57 -0
- package/templates/storefront/src/styles/ub/showcase.css +85 -0
- package/templates/storefront/src/styles/ub/variants.css +64 -0
- package/templates/storefront/themes/black-friday-2/campaign.en.json +31 -0
- package/templates/storefront/themes/black-friday-2/campaign.fr.json +31 -0
- package/templates/storefront/themes/black-friday-2/theme.json +10 -0
- package/templates/storefront/themes/cyber-monday-2/campaign.en.json +31 -0
- package/templates/storefront/themes/cyber-monday-2/campaign.fr.json +31 -0
- package/templates/storefront/themes/cyber-monday-2/theme.json +10 -0
- package/templates/storefront/themes/halloween-2/campaign.en.json +31 -0
- package/templates/storefront/themes/halloween-2/campaign.fr.json +31 -0
- package/templates/storefront/themes/halloween-2/theme.json +10 -0
- package/templates/storefront/themes/noel-2/campaign.en.json +31 -0
- package/templates/storefront/themes/noel-2/campaign.fr.json +31 -0
- package/templates/storefront/themes/noel-2/theme.json +10 -0
- package/templates/storefront/themes/nouvel-an-2/campaign.en.json +31 -0
- package/templates/storefront/themes/nouvel-an-2/campaign.fr.json +31 -0
- package/templates/storefront/themes/nouvel-an-2/theme.json +10 -0
- package/templates/storefront/themes/thanksgiving-2/campaign.en.json +31 -0
- package/templates/storefront/themes/thanksgiving-2/campaign.fr.json +31 -0
- package/templates/storefront/themes/thanksgiving-2/theme.json +10 -0
|
@@ -9,6 +9,7 @@ import { Hero, PromoBanner, SectionHead, TrustBar } from "@modules/ub/campaign-b
|
|
|
9
9
|
import CampaignEnded from "@modules/ub/campaign-ended"
|
|
10
10
|
import CategoryTiles from "@modules/ub/category-tiles"
|
|
11
11
|
import { ProductGrid } from "@modules/ub/product-card"
|
|
12
|
+
import { DealsFold, DealsSpotlight } from "@modules/ub/showcase"
|
|
12
13
|
|
|
13
14
|
async function Categories({ title }: { title: string }) {
|
|
14
15
|
const categories = await listCategories().catch(() => [])
|
|
@@ -40,6 +41,24 @@ async function Products({ title }: { title: string }) {
|
|
|
40
41
|
)
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
/** Vitrines interactives : accordion « offres phares » puis grande carte sombre (produits les plus remisés d'abord). */
|
|
45
|
+
async function Showcase({ part, eyebrow }: { part: "fold" | "spotlight"; eyebrow?: string }) {
|
|
46
|
+
const {
|
|
47
|
+
response: { products },
|
|
48
|
+
} = await listProducts({ queryParams: { limit: 12, fields: "*categories,*collection" } })
|
|
49
|
+
const off = (p: (typeof products)[number]) =>
|
|
50
|
+
Math.max(0, ...(p.variants ?? []).map((v) => {
|
|
51
|
+
const c = v.calculated_price
|
|
52
|
+
return c?.original_amount && c.calculated_amount != null ? 1 - c.calculated_amount / c.original_amount : 0
|
|
53
|
+
}))
|
|
54
|
+
const sorted = [...products].sort((a, b) => off(b) - off(a))
|
|
55
|
+
return part === "fold" ? (
|
|
56
|
+
<DealsFold products={sorted} title={t("section.fold")} />
|
|
57
|
+
) : (
|
|
58
|
+
<DealsSpotlight products={sorted.slice(5)} eyebrow={eyebrow} title={t("section.spotlight")} />
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
43
62
|
function GridFallback() {
|
|
44
63
|
return <div className="ub-section" aria-busy="true" style={{ minHeight: 320 }} />
|
|
45
64
|
}
|
|
@@ -56,9 +75,15 @@ export default async function Home() {
|
|
|
56
75
|
<>
|
|
57
76
|
<Hero campaign={campaign} />
|
|
58
77
|
<TrustBar freeShipping={campaign.freeShipping} />
|
|
78
|
+
<Suspense fallback={<GridFallback />}>
|
|
79
|
+
<Showcase part="fold" />
|
|
80
|
+
</Suspense>
|
|
59
81
|
<Suspense fallback={<GridFallback />}>
|
|
60
82
|
<Categories title={campaign.sections?.categories ?? t("section.categories")} />
|
|
61
83
|
</Suspense>
|
|
84
|
+
<Suspense fallback={<GridFallback />}>
|
|
85
|
+
<Showcase part="spotlight" eyebrow={campaign.hero.eyebrow} />
|
|
86
|
+
</Suspense>
|
|
62
87
|
<PromoBanner campaign={campaign} />
|
|
63
88
|
<Suspense fallback={<GridFallback />}>
|
|
64
89
|
<Products title={campaign.sections?.products ?? t("section.products")} />
|
|
@@ -12,17 +12,19 @@ type Params = {
|
|
|
12
12
|
searchParams: Promise<{
|
|
13
13
|
sortBy?: SortOptions
|
|
14
14
|
page?: string
|
|
15
|
+
category?: string
|
|
15
16
|
}>
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export default async function StorePage(props: Params) {
|
|
19
20
|
const searchParams = await props.searchParams;
|
|
20
|
-
const { sortBy, page } = searchParams
|
|
21
|
+
const { sortBy, page, category } = searchParams
|
|
21
22
|
|
|
22
23
|
return (
|
|
23
24
|
<StoreTemplate
|
|
24
25
|
sortBy={sortBy}
|
|
25
26
|
page={page}
|
|
27
|
+
category={category}
|
|
26
28
|
/>
|
|
27
29
|
)
|
|
28
30
|
}
|
|
@@ -7,6 +7,13 @@ import { Metadata } from "next"
|
|
|
7
7
|
import "styles/globals.css"
|
|
8
8
|
import "styles/ub/tokens.css"
|
|
9
9
|
import "styles/ub/bundle.css"
|
|
10
|
+
import "styles/ub/variants.css"
|
|
11
|
+
import "styles/ub/pages.css"
|
|
12
|
+
import "styles/ub/showcase.css"
|
|
13
|
+
import "styles/ub/forms.css"
|
|
14
|
+
import "styles/ub/account.css"
|
|
15
|
+
import "styles/ub/black-friday.css"
|
|
16
|
+
import "styles/ub/responsive.css"
|
|
10
17
|
import "styles/ub/fonts.css"
|
|
11
18
|
import "styles/ub/medusa-ui.css"
|
|
12
19
|
import "styles/ub/overrides.css"
|
|
@@ -31,9 +38,9 @@ export default function RootLayout(props: { children: React.ReactNode }) {
|
|
|
31
38
|
const b = getBoutique()
|
|
32
39
|
|
|
33
40
|
return (
|
|
34
|
-
<html lang={b.locale} data-theme={b.theme.id} data-mode="light" className={themeFontClasses(b.theme)}>
|
|
41
|
+
<html lang={b.locale} data-theme={b.theme.layout ?? b.theme.id} data-variant={b.theme.layout ? b.theme.id : undefined} data-mode="light" className={themeFontClasses(b.theme)}>
|
|
35
42
|
<body className="ub">
|
|
36
|
-
<I18nProvider messages={messages("")}>
|
|
43
|
+
<I18nProvider messages={messages("")} locale={b.locale}>
|
|
37
44
|
<main className="relative">{props.children}</main>
|
|
38
45
|
</I18nProvider>
|
|
39
46
|
</body>
|
|
@@ -95,6 +95,7 @@ function load(): Boutique {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
const theme = loadTheme(entry.theme)
|
|
98
|
+
if (theme.layout) loadTheme(theme.layout) // variante : la mise en page empruntée doit exister
|
|
98
99
|
|
|
99
100
|
const keyFile = path.join(/*turbopackIgnore: true*/ KEYS_DIR, slug)
|
|
100
101
|
let publishableKey = ""
|
|
@@ -5,15 +5,23 @@ import { createContext, useContext } from "react"
|
|
|
5
5
|
type Dict = Record<string, string>
|
|
6
6
|
|
|
7
7
|
const I18nContext = createContext<Dict>({})
|
|
8
|
+
/** Locale de l'instance (ex. fr-SN) : langue du site + pays de la boutique. */
|
|
9
|
+
const LocaleContext = createContext("en-US")
|
|
8
10
|
|
|
9
11
|
/**
|
|
10
12
|
* Dictionnaire de l'instance pour les composants client (checkout, panier, compte).
|
|
11
13
|
* Rempli par le layout racine (serveur) avec locales/<lang>.json + repli anglais.
|
|
12
14
|
*/
|
|
13
|
-
export function I18nProvider({ messages, children }: { messages: Dict; children: React.ReactNode }) {
|
|
14
|
-
return
|
|
15
|
+
export function I18nProvider({ messages, locale = "en-US", children }: { messages: Dict; locale?: string; children: React.ReactNode }) {
|
|
16
|
+
return (
|
|
17
|
+
<LocaleContext.Provider value={locale}>
|
|
18
|
+
<I18nContext.Provider value={messages}>{children}</I18nContext.Provider>
|
|
19
|
+
</LocaleContext.Provider>
|
|
20
|
+
)
|
|
15
21
|
}
|
|
16
22
|
|
|
23
|
+
export const useLocale = () => useContext(LocaleContext)
|
|
24
|
+
|
|
17
25
|
export function format(text: string, vars?: Record<string, string | number>) {
|
|
18
26
|
return vars ? text.replace(/\{(\w+)\}/g, (m, k: string) => (k in vars ? String(vars[k]) : m)) : text
|
|
19
27
|
}
|
|
@@ -68,6 +68,8 @@ export const themeSchema = z.object({
|
|
|
68
68
|
id: z.string().regex(SLUG),
|
|
69
69
|
name: z.string().min(1),
|
|
70
70
|
reference: z.string().optional(),
|
|
71
|
+
/** Variante : reprend la mise en page (règles CSS) de ce thème, avec la palette de styles/ub/variants.css. */
|
|
72
|
+
layout: z.string().regex(SLUG).optional(),
|
|
71
73
|
fonts: z.object({
|
|
72
74
|
head: z.enum(["inter", "jakarta", "oswald", "outfit", "poppins", "serif", "sora", "space-grotesk"]),
|
|
73
75
|
body: z.enum(["inter", "jakarta", "oswald", "outfit", "poppins", "serif", "sora", "space-grotesk"]),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from "react"
|
|
2
2
|
import { CreditCard } from "@medusajs/icons"
|
|
3
|
+
import { T } from "@lib/boutique/i18n-client"
|
|
3
4
|
|
|
4
5
|
import Ideal from "@modules/common/icons/ideal"
|
|
5
6
|
import Bancontact from "@modules/common/icons/bancontact"
|
|
@@ -8,14 +9,14 @@ import PayPal from "@modules/common/icons/paypal"
|
|
|
8
9
|
/* Map of payment provider_id to their title and icon. Add in any payment providers you want to use. */
|
|
9
10
|
export const paymentInfoMap: Record<
|
|
10
11
|
string,
|
|
11
|
-
{ title:
|
|
12
|
+
{ title: React.ReactNode; icon: React.JSX.Element }
|
|
12
13
|
> = {
|
|
13
14
|
pp_stripe_stripe: {
|
|
14
|
-
title: "
|
|
15
|
+
title: <T k="checkout.cardAndWallets" />,
|
|
15
16
|
icon: <CreditCard />,
|
|
16
17
|
},
|
|
17
18
|
"pp_medusa-payments_default": {
|
|
18
|
-
title: "
|
|
19
|
+
title: <T k="checkout.cardAndWallets" />,
|
|
19
20
|
icon: <CreditCard />,
|
|
20
21
|
},
|
|
21
22
|
"pp_stripe-ideal_stripe": {
|
|
@@ -31,7 +32,7 @@ export const paymentInfoMap: Record<
|
|
|
31
32
|
icon: <PayPal />,
|
|
32
33
|
},
|
|
33
34
|
pp_system_default: {
|
|
34
|
-
title: "
|
|
35
|
+
title: <T k="checkout.manualPayment" />,
|
|
35
36
|
icon: <CreditCard />,
|
|
36
37
|
},
|
|
37
38
|
// Add more payment providers here
|
|
@@ -1,197 +1,70 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
import { T } from "@lib/boutique/i18n-client"
|
|
5
|
-
import { clx } from "@medusajs/ui"
|
|
6
4
|
import { ArrowRightOnRectangle } from "@medusajs/icons"
|
|
7
5
|
import { usePathname } from "next/navigation"
|
|
8
6
|
|
|
9
|
-
import
|
|
10
|
-
import User from "@modules/common/icons/user"
|
|
7
|
+
import LocalizedClientLink from "@modules/common/components/localized-client-link"
|
|
11
8
|
import MapPin from "@modules/common/icons/map-pin"
|
|
12
9
|
import Package from "@modules/common/icons/package"
|
|
13
|
-
import
|
|
10
|
+
import User from "@modules/common/icons/user"
|
|
11
|
+
import { Icon } from "@modules/ub/icons"
|
|
14
12
|
import { HttpTypes } from "@medusajs/types"
|
|
15
13
|
import { signout } from "@lib/data/customer"
|
|
16
14
|
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
15
|
+
const LINKS = [
|
|
16
|
+
{ href: "/account", key: "account.overview", testId: "overview-link", icon: <Icon name="home" /> },
|
|
17
|
+
{ href: "/account/profile", key: "account.profile", testId: "profile-link", icon: <User size={20} /> },
|
|
18
|
+
{ href: "/account/addresses", key: "account.addresses", testId: "addresses-link", icon: <MapPin size={20} /> },
|
|
19
|
+
{ href: "/account/orders", key: "account.orders", testId: "orders-link", icon: <Package size={20} /> },
|
|
20
|
+
]
|
|
23
21
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
/** Menu du compte : carte client (initiales, nom, e-mail) + liens avec icônes ; pastilles défilantes sur mobile. */
|
|
23
|
+
const AccountNav = ({ customer }: { customer: HttpTypes.StoreCustomer | null }) => {
|
|
24
|
+
const route = usePathname()
|
|
25
|
+
const initials = `${customer?.first_name?.[0] ?? ""}${customer?.last_name?.[0] ?? ""}`.toUpperCase() || "•"
|
|
26
|
+
const name = [customer?.first_name, customer?.last_name].filter(Boolean).join(" ")
|
|
27
27
|
|
|
28
28
|
return (
|
|
29
|
-
<
|
|
30
|
-
<div className="
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
>
|
|
37
|
-
|
|
38
|
-
<ChevronDown className="transform rotate-90" />
|
|
39
|
-
<span><T k="account.title" /></span>
|
|
40
|
-
</>
|
|
41
|
-
</LocalizedClientLink>
|
|
42
|
-
) : (
|
|
43
|
-
<>
|
|
44
|
-
<div className="text-xl-semi mb-4 px-8">
|
|
45
|
-
Hello {customer?.first_name}
|
|
46
|
-
</div>
|
|
47
|
-
<div className="text-base-regular">
|
|
48
|
-
<ul>
|
|
49
|
-
<li>
|
|
50
|
-
<LocalizedClientLink
|
|
51
|
-
href="/account/profile"
|
|
52
|
-
className="flex items-center justify-between py-4 border-b border-gray-200 px-8"
|
|
53
|
-
data-testid="profile-link"
|
|
54
|
-
>
|
|
55
|
-
<>
|
|
56
|
-
<div className="flex items-center gap-x-2">
|
|
57
|
-
<User size={20} />
|
|
58
|
-
<span><T k="account.profile" /></span>
|
|
59
|
-
</div>
|
|
60
|
-
<ChevronDown className="transform -rotate-90" />
|
|
61
|
-
</>
|
|
62
|
-
</LocalizedClientLink>
|
|
63
|
-
</li>
|
|
64
|
-
<li>
|
|
65
|
-
<LocalizedClientLink
|
|
66
|
-
href="/account/addresses"
|
|
67
|
-
className="flex items-center justify-between py-4 border-b border-gray-200 px-8"
|
|
68
|
-
data-testid="addresses-link"
|
|
69
|
-
>
|
|
70
|
-
<>
|
|
71
|
-
<div className="flex items-center gap-x-2">
|
|
72
|
-
<MapPin size={20} />
|
|
73
|
-
<span><T k="account.addresses" /></span>
|
|
74
|
-
</div>
|
|
75
|
-
<ChevronDown className="transform -rotate-90" />
|
|
76
|
-
</>
|
|
77
|
-
</LocalizedClientLink>
|
|
78
|
-
</li>
|
|
79
|
-
<li>
|
|
80
|
-
<LocalizedClientLink
|
|
81
|
-
href="/account/orders"
|
|
82
|
-
className="flex items-center justify-between py-4 border-b border-gray-200 px-8"
|
|
83
|
-
data-testid="orders-link"
|
|
84
|
-
>
|
|
85
|
-
<div className="flex items-center gap-x-2">
|
|
86
|
-
<Package size={20} />
|
|
87
|
-
<span><T k="account.orders" /></span>
|
|
88
|
-
</div>
|
|
89
|
-
<ChevronDown className="transform -rotate-90" />
|
|
90
|
-
</LocalizedClientLink>
|
|
91
|
-
</li>
|
|
92
|
-
<li>
|
|
93
|
-
<button
|
|
94
|
-
type="button"
|
|
95
|
-
className="flex items-center justify-between py-4 border-b border-gray-200 px-8 w-full"
|
|
96
|
-
onClick={handleLogout}
|
|
97
|
-
data-testid="logout-button"
|
|
98
|
-
>
|
|
99
|
-
<div className="flex items-center gap-x-2">
|
|
100
|
-
<ArrowRightOnRectangle />
|
|
101
|
-
<span><T k="account.logout" /></span>
|
|
102
|
-
</div>
|
|
103
|
-
<ChevronDown className="transform -rotate-90" />
|
|
104
|
-
</button>
|
|
105
|
-
</li>
|
|
106
|
-
</ul>
|
|
107
|
-
</div>
|
|
108
|
-
</>
|
|
109
|
-
)}
|
|
29
|
+
<aside className="ub-accnav" data-testid="account-nav">
|
|
30
|
+
<div className="ub-accnav__me">
|
|
31
|
+
<span className="ub-accnav__avatar" aria-hidden>
|
|
32
|
+
{initials}
|
|
33
|
+
</span>
|
|
34
|
+
<span className="ub-accnav__who">
|
|
35
|
+
<b>{name || <T k="account.title" />}</b>
|
|
36
|
+
{customer?.email && <small>{customer.email}</small>}
|
|
37
|
+
</span>
|
|
110
38
|
</div>
|
|
111
|
-
<
|
|
112
|
-
<
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
data-testid="overview-link"
|
|
123
|
-
>
|
|
124
|
-
<T k="account.overview" />
|
|
125
|
-
</AccountNavLink>
|
|
126
|
-
</li>
|
|
127
|
-
<li>
|
|
128
|
-
<AccountNavLink
|
|
129
|
-
href="/account/profile"
|
|
130
|
-
route={route!}
|
|
131
|
-
data-testid="profile-link"
|
|
132
|
-
>
|
|
133
|
-
<T k="account.profile" />
|
|
134
|
-
</AccountNavLink>
|
|
135
|
-
</li>
|
|
136
|
-
<li>
|
|
137
|
-
<AccountNavLink
|
|
138
|
-
href="/account/addresses"
|
|
139
|
-
route={route!}
|
|
140
|
-
data-testid="addresses-link"
|
|
39
|
+
<nav aria-label="account">
|
|
40
|
+
<ul className="ub-accnav__list">
|
|
41
|
+
{LINKS.map((l) => {
|
|
42
|
+
const active = l.href === "/account" ? route === l.href : route?.startsWith(l.href)
|
|
43
|
+
return (
|
|
44
|
+
<li key={l.href}>
|
|
45
|
+
<LocalizedClientLink
|
|
46
|
+
href={l.href}
|
|
47
|
+
className="ub-accnav__link"
|
|
48
|
+
aria-current={active ? "page" : undefined}
|
|
49
|
+
data-testid={l.testId}
|
|
141
50
|
>
|
|
142
|
-
<
|
|
143
|
-
|
|
51
|
+
<span className="ub-accnav__ic">{l.icon}</span>
|
|
52
|
+
<T k={l.key} />
|
|
53
|
+
</LocalizedClientLink>
|
|
144
54
|
</li>
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
data-testid="logout-button"
|
|
159
|
-
>
|
|
160
|
-
<T k="account.logout" />
|
|
161
|
-
</button>
|
|
162
|
-
</li>
|
|
163
|
-
</ul>
|
|
164
|
-
</div>
|
|
165
|
-
</div>
|
|
166
|
-
</div>
|
|
167
|
-
</div>
|
|
168
|
-
)
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
type AccountNavLinkProps = {
|
|
172
|
-
href: string
|
|
173
|
-
route: string
|
|
174
|
-
children: React.ReactNode
|
|
175
|
-
"data-testid"?: string
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const AccountNavLink = ({
|
|
179
|
-
href,
|
|
180
|
-
route,
|
|
181
|
-
children,
|
|
182
|
-
"data-testid": dataTestId,
|
|
183
|
-
}: AccountNavLinkProps) => {
|
|
184
|
-
const active = route === href
|
|
185
|
-
return (
|
|
186
|
-
<LocalizedClientLink
|
|
187
|
-
href={href}
|
|
188
|
-
className={clx("text-ui-fg-subtle hover:text-ui-fg-base", {
|
|
189
|
-
"text-ui-fg-base font-semibold": active,
|
|
190
|
-
})}
|
|
191
|
-
data-testid={dataTestId}
|
|
192
|
-
>
|
|
193
|
-
{children}
|
|
194
|
-
</LocalizedClientLink>
|
|
55
|
+
)
|
|
56
|
+
})}
|
|
57
|
+
<li>
|
|
58
|
+
<button type="button" className="ub-accnav__link ub-accnav__logout" onClick={() => signout()} data-testid="logout-button">
|
|
59
|
+
<span className="ub-accnav__ic">
|
|
60
|
+
<ArrowRightOnRectangle />
|
|
61
|
+
</span>
|
|
62
|
+
<T k="account.logout" />
|
|
63
|
+
</button>
|
|
64
|
+
</li>
|
|
65
|
+
</ul>
|
|
66
|
+
</nav>
|
|
67
|
+
</aside>
|
|
195
68
|
)
|
|
196
69
|
}
|
|
197
70
|
|
|
@@ -9,6 +9,7 @@ import { useEffect, useState, useActionState } from "react"
|
|
|
9
9
|
import useToggleState from "@lib/hooks/use-toggle-state"
|
|
10
10
|
import CountrySelect from "@modules/checkout/components/country-select"
|
|
11
11
|
import Input from "@modules/common/components/input"
|
|
12
|
+
import PhoneInput from "@modules/common/components/phone-input"
|
|
12
13
|
import Modal from "@modules/common/components/modal"
|
|
13
14
|
import { SubmitButton } from "@modules/checkout/components/submit-button"
|
|
14
15
|
import { HttpTypes } from "@medusajs/types"
|
|
@@ -130,10 +131,9 @@ const AddAddress = ({
|
|
|
130
131
|
autoComplete="country"
|
|
131
132
|
data-testid="country-select"
|
|
132
133
|
/>
|
|
133
|
-
<
|
|
134
|
+
<PhoneInput
|
|
134
135
|
label="form.phone"
|
|
135
136
|
name="phone"
|
|
136
|
-
autoComplete="phone"
|
|
137
137
|
data-testid="phone-input"
|
|
138
138
|
/>
|
|
139
139
|
</div>
|
package/templates/storefront/src/modules/account/components/address-card/edit-address-modal.tsx
CHANGED
|
@@ -9,6 +9,7 @@ import { Button, Heading, Text, clx } from "@medusajs/ui"
|
|
|
9
9
|
import useToggleState from "@lib/hooks/use-toggle-state"
|
|
10
10
|
import CountrySelect from "@modules/checkout/components/country-select"
|
|
11
11
|
import Input from "@modules/common/components/input"
|
|
12
|
+
import PhoneInput from "@modules/common/components/phone-input"
|
|
12
13
|
import Modal from "@modules/common/components/modal"
|
|
13
14
|
import Spinner from "@modules/common/icons/spinner"
|
|
14
15
|
import { SubmitButton } from "@modules/checkout/components/submit-button"
|
|
@@ -204,10 +205,9 @@ const EditAddress: React.FC<EditAddressProps> = ({
|
|
|
204
205
|
defaultValue={address.country_code || undefined}
|
|
205
206
|
data-testid="country-select"
|
|
206
207
|
/>
|
|
207
|
-
<
|
|
208
|
+
<PhoneInput
|
|
208
209
|
label="form.phone"
|
|
209
210
|
name="phone"
|
|
210
|
-
autoComplete="phone"
|
|
211
211
|
defaultValue={address.phone || undefined}
|
|
212
212
|
data-testid="phone-input"
|
|
213
213
|
/>
|