@salifbiaye/create-boutique 0.2.0 → 0.2.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.
- package/package.json +1 -1
- package/templates/backend/src/admin/routes/boutique-campaigns/page.tsx +23 -1
- package/templates/storefront/locales/en.json +2 -1
- package/templates/storefront/locales/fr.json +2 -1
- package/templates/storefront/src/modules/account/components/order-card/index.tsx +2 -1
- package/templates/storefront/src/modules/cart/components/cart-item-select/index.tsx +1 -1
- package/templates/storefront/src/modules/checkout/components/payment-wrapper/index.tsx +1 -1
- package/templates/storefront/src/modules/common/components/line-item-options/index.tsx +2 -1
- package/templates/storefront/src/modules/common/components/local-date/index.tsx +9 -0
- package/templates/storefront/src/modules/order/components/order-details/index.tsx +2 -1
- package/templates/storefront/src/modules/order/components/shipping-details/index.tsx +1 -1
- package/templates/storefront/src/styles/ub/medusa-ui.css +18 -1
- package/templates/storefront/src/styles/ub/responsive.css +26 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salifbiaye/create-boutique",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Usine à Boutiques : génère un projet complet (backend Medusa + une boutique Next.js par campagne) prêt pour docker compose",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": { "type": "git", "url": "git+https://github.com/salifbiaye/create-boutique.git" },
|
|
@@ -19,6 +19,28 @@ function status(c: Boutique["campaign"]): "upcoming" | "live" | "ended" | null {
|
|
|
19
19
|
|
|
20
20
|
const COLORS = { upcoming: "blue", live: "green", ended: "grey" } as const
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Ouvre le panneau avec la campagne relue sur le serveur (jamais la copie du tableau) : sinon, rouvrir juste après
|
|
24
|
+
* un enregistrement pouvait repartir d'anciennes valeurs et réenregistrer l'ancienne image.
|
|
25
|
+
*/
|
|
26
|
+
function FreshCampaignDrawer(props: Omit<Parameters<typeof CampaignDrawer>[0], "boutique"> & { boutique: Boutique }) {
|
|
27
|
+
const { boutique, ...rest } = props
|
|
28
|
+
const { data, isFetching } = useQuery({
|
|
29
|
+
queryKey: [...QUERY_KEY, "one", boutique.sales_channel_id],
|
|
30
|
+
queryFn: () => sdk.client.fetch<{ campaign: Boutique["campaign"] }>(`/admin/boutique-campaigns/${boutique.sales_channel_id}`),
|
|
31
|
+
staleTime: 0,
|
|
32
|
+
gcTime: 0,
|
|
33
|
+
})
|
|
34
|
+
if (!data || isFetching) {
|
|
35
|
+
return (
|
|
36
|
+
<div className="fixed inset-0 z-50 flex items-center justify-center bg-ui-bg-overlay">
|
|
37
|
+
<Spinner className="animate-spin" />
|
|
38
|
+
</div>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
return <CampaignDrawer {...rest} boutique={{ ...boutique, campaign: data.campaign ?? null }} />
|
|
42
|
+
}
|
|
43
|
+
|
|
22
44
|
/** Page « Campagnes » : une ligne par boutique du projet, édition dans un panneau latéral. */
|
|
23
45
|
const CampaignsPage = () => {
|
|
24
46
|
const { t, i18n } = useTranslation()
|
|
@@ -93,7 +115,7 @@ const CampaignsPage = () => {
|
|
|
93
115
|
)}
|
|
94
116
|
|
|
95
117
|
{editing && (
|
|
96
|
-
<
|
|
118
|
+
<FreshCampaignDrawer
|
|
97
119
|
boutique={editing}
|
|
98
120
|
others={(data?.boutiques ?? []).filter((b) => b.sales_channel_id !== editing.sales_channel_id).map((b) => b.slug)}
|
|
99
121
|
queryKey={QUERY_KEY}
|
|
@@ -302,5 +302,6 @@
|
|
|
302
302
|
"account.keepShopping": "Shop the deals",
|
|
303
303
|
"account.profileDone": "Profile completed",
|
|
304
304
|
"account.completeProfile": "Complete your profile (phone, billing address) to check out faster.",
|
|
305
|
-
"nav.menu": "Menu"
|
|
305
|
+
"nav.menu": "Menu",
|
|
306
|
+
"cart.variant": "Variant:"
|
|
306
307
|
}
|
|
@@ -302,5 +302,6 @@
|
|
|
302
302
|
"account.keepShopping": "Voir les offres",
|
|
303
303
|
"account.profileDone": "Profil complété",
|
|
304
304
|
"account.completeProfile": "Complétez votre profil (téléphone, adresse de facturation) pour commander plus vite.",
|
|
305
|
-
"nav.menu": "Menu"
|
|
305
|
+
"nav.menu": "Menu",
|
|
306
|
+
"cart.variant": "Variante :"
|
|
306
307
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { T } from "@lib/boutique/i18n-client"
|
|
2
|
+
import LocalDate from "@modules/common/components/local-date"
|
|
2
3
|
import { Button } from "@medusajs/ui"
|
|
3
4
|
import { useMemo } from "react"
|
|
4
5
|
|
|
@@ -31,7 +32,7 @@ const OrderCard = ({ order }: OrderCardProps) => {
|
|
|
31
32
|
</div>
|
|
32
33
|
<div className="flex items-center divide-x divide-gray-200 text-small-regular text-ui-fg-base">
|
|
33
34
|
<span className="pr-2" data-testid="order-created-at">
|
|
34
|
-
{
|
|
35
|
+
<LocalDate iso={order.created_at} style="medium" />
|
|
35
36
|
</span>
|
|
36
37
|
<span className="px-2" data-testid="order-amount">
|
|
37
38
|
{convertToLocale({
|
|
@@ -44,7 +44,7 @@ const CartItemSelect = forwardRef<HTMLSelectElement, NativeSelectProps>(
|
|
|
44
44
|
onFocus={() => innerRef.current?.focus()}
|
|
45
45
|
onBlur={() => innerRef.current?.blur()}
|
|
46
46
|
className={clx(
|
|
47
|
-
"relative flex items-center txt-compact-small border text-ui-fg-base group",
|
|
47
|
+
"ub-qty relative flex items-center txt-compact-small border text-ui-fg-base group",
|
|
48
48
|
className,
|
|
49
49
|
{
|
|
50
50
|
"text-ui-fg-subtle": isPlaceholder,
|
|
@@ -14,7 +14,7 @@ type PaymentWrapperProps = {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
const PaymentWrapper: React.FC<PaymentWrapperProps> = ({ cart, stripeKey, children }) => {
|
|
17
|
-
const stripePromise = useMemo(() => (stripeKey ? loadStripe(stripeKey) : null), [stripeKey])
|
|
17
|
+
const stripePromise = useMemo(() => (stripeKey ? loadStripe(stripeKey, { developerTools: { assistant: { enabled: false } } }) : null), [stripeKey])
|
|
18
18
|
|
|
19
19
|
const paymentSession = cart.payment_collection?.payment_sessions?.find(
|
|
20
20
|
(s) => s.status === "pending"
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { T } from "@lib/boutique/i18n-client"
|
|
1
2
|
import { HttpTypes } from "@medusajs/types"
|
|
2
3
|
import { Text } from "@medusajs/ui"
|
|
3
4
|
|
|
@@ -18,7 +19,7 @@ const LineItemOptions = ({
|
|
|
18
19
|
data-value={dataValue}
|
|
19
20
|
className="inline-block txt-medium text-ui-fg-subtle w-full overflow-hidden text-ellipsis"
|
|
20
21
|
>
|
|
21
|
-
|
|
22
|
+
<T k="cart.variant" /> {variant?.title}
|
|
22
23
|
</Text>
|
|
23
24
|
)
|
|
24
25
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { useLocale } from "@lib/boutique/i18n-client"
|
|
4
|
+
|
|
5
|
+
/** Date formatée dans la langue et le pays de la boutique (ex. « 29 septembre 2026 » en fr-FR). */
|
|
6
|
+
export default function LocalDate({ iso, style = "long" }: { iso: string | Date; style?: "long" | "medium" | "short" }) {
|
|
7
|
+
const locale = useLocale()
|
|
8
|
+
return <>{new Date(iso).toLocaleDateString(locale, { dateStyle: style })}</>
|
|
9
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { T } from "@lib/boutique/i18n-client"
|
|
2
|
+
import LocalDate from "@modules/common/components/local-date"
|
|
2
3
|
import { HttpTypes } from "@medusajs/types"
|
|
3
4
|
import { Text } from "@medusajs/ui"
|
|
4
5
|
|
|
@@ -29,7 +30,7 @@ const OrderDetails = ({ order, showStatus }: OrderDetailsProps) => {
|
|
|
29
30
|
<Text className="mt-2">
|
|
30
31
|
<T k="order.date" />{" "}
|
|
31
32
|
<span data-testid="order-date">
|
|
32
|
-
{
|
|
33
|
+
<LocalDate iso={order.created_at} />
|
|
33
34
|
</span>
|
|
34
35
|
</Text>
|
|
35
36
|
<Text className="mt-2 text-ui-fg-interactive">
|
|
@@ -55,7 +55,7 @@ const ShippingDetails = ({ order }: ShippingDetailsProps) => {
|
|
|
55
55
|
className="flex flex-col w-1/3"
|
|
56
56
|
data-testid="shipping-method-summary"
|
|
57
57
|
>
|
|
58
|
-
<Text className="txt-medium-plus text-ui-fg-base mb-1"
|
|
58
|
+
<Text className="txt-medium-plus text-ui-fg-base mb-1"><T k="order.method" /></Text>
|
|
59
59
|
<Text className="txt-medium text-ui-fg-subtle">
|
|
60
60
|
{(order as any).shipping_methods[0]?.name} (
|
|
61
61
|
{convertToLocale({
|
|
@@ -91,9 +91,26 @@ html[data-theme] {
|
|
|
91
91
|
|
|
92
92
|
/* Couleurs Tailwind écrites en dur dans le starter (compte, panier, checkout, squelettes de chargement) :
|
|
93
93
|
ramenées aux tokens du thème, sinon un thème sombre affiche des blocs blancs au texte illisible. */
|
|
94
|
-
|
|
94
|
+
/* bg-white = conteneurs de page du starter (étapes du checkout, résumé, code promo) sans marge intérieure :
|
|
95
|
+
transparents (en surface grise, leur contenu collé aux bords paraissait coupé). Menus déroulants : surface. */
|
|
96
|
+
.ub .bg-white {
|
|
97
|
+
background-color: transparent;
|
|
98
|
+
}
|
|
99
|
+
.ub .bg-white:is(.absolute, .fixed),
|
|
100
|
+
.ub :is(.bg-gray-50, .bg-neutral-50) {
|
|
95
101
|
background-color: var(--surface);
|
|
96
102
|
}
|
|
103
|
+
/* Sélecteur de quantité (IconBadge de Medusa UI, fond blanc imposé) et listes déroulantes natives */
|
|
104
|
+
.ub .ub-qty {
|
|
105
|
+
background: var(--bg-field) !important;
|
|
106
|
+
border-color: var(--border-base) !important;
|
|
107
|
+
color: var(--ink) !important;
|
|
108
|
+
border-radius: var(--ub-r-btn);
|
|
109
|
+
}
|
|
110
|
+
.ub select option {
|
|
111
|
+
background: var(--surface);
|
|
112
|
+
color: var(--ink);
|
|
113
|
+
}
|
|
97
114
|
.ub :is(.bg-gray-100, .bg-neutral-100) {
|
|
98
115
|
background-color: var(--tint-1);
|
|
99
116
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* Mobile et tablette : menu burger, bandeau plus compact, pas de débordement horizontal. */
|
|
2
2
|
.ub-burger { display: none; }
|
|
3
|
+
.ub-burger:not([open]) .ub-burger__panel { display: none; }
|
|
3
4
|
|
|
4
5
|
@media (max-width: 900px) {
|
|
5
6
|
html, body { overflow-x: clip; }
|
|
@@ -35,6 +36,22 @@
|
|
|
35
36
|
|
|
36
37
|
.ub-section { padding: var(--space-8) 0; }
|
|
37
38
|
.ub-wrap { padding: 0 var(--space-4); }
|
|
39
|
+
|
|
40
|
+
/* Bandeau promo : marges réduites, contenu sur toute la largeur */
|
|
41
|
+
.ub-promo { padding: var(--space-8) var(--space-6) !important; gap: var(--space-6) !important; min-width: 0; }
|
|
42
|
+
.ub-promo__text { min-width: 0; }
|
|
43
|
+
.ub-promo__media { height: 200px; }
|
|
44
|
+
|
|
45
|
+
/* Compte à rebours : les 4 cases se partagent la largeur (plus de débordement) */
|
|
46
|
+
.ub-countdown { width: 100%; max-width: 360px; gap: 6px; }
|
|
47
|
+
.ub-countdown__c { flex: 1 1 0; min-width: 0 !important; }
|
|
48
|
+
|
|
49
|
+
/* Carte d'offres (sombre ou jaune) : pas de retrait sous le numéro, prix + bouton qui passent à la ligne */
|
|
50
|
+
.ub-spot { padding: var(--space-8) var(--space-4); }
|
|
51
|
+
.ub-spot__head { margin-bottom: var(--space-8); }
|
|
52
|
+
.ub-spot__label { padding: var(--space-4) !important; gap: var(--space-3) !important; }
|
|
53
|
+
.ub-spot__more p { padding: 0 var(--space-4) var(--space-3) !important; }
|
|
54
|
+
.ub-spot__buy { flex-wrap: wrap; padding: 0 var(--space-4) var(--space-4) !important; gap: var(--space-3); }
|
|
38
55
|
}
|
|
39
56
|
|
|
40
57
|
@media (max-width: 600px) {
|
|
@@ -54,4 +71,13 @@
|
|
|
54
71
|
.ub-badge { font-size: 11px !important; padding: 3px 7px !important; }
|
|
55
72
|
.ub-trust { gap: var(--space-3) !important; }
|
|
56
73
|
.ub-sec-head h2 { font-size: 22px; line-height: 28px; }
|
|
74
|
+
|
|
75
|
+
.ub-promo { padding: var(--space-6) var(--space-4) !important; }
|
|
76
|
+
.ub-promo h2 { font-size: 26px !important; line-height: 30px !important; }
|
|
77
|
+
.ub-promo__media { height: 160px; }
|
|
78
|
+
.ub-countdown__c { height: 54px !important; }
|
|
79
|
+
.ub-countdown__c b { font-size: 19px !important; line-height: 22px !important; }
|
|
80
|
+
.ub-countdown__c small { font-size: 10px !important; }
|
|
81
|
+
.ub-spot__name { font-size: 16px; }
|
|
82
|
+
.ub-spot__cta { padding: 8px 14px; }
|
|
57
83
|
}
|