@faststore/core 3.64.0 → 3.65.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.
Files changed (166) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +49 -49
  3. package/.next/cache/.tsbuildinfo +1 -1
  4. package/.next/cache/config.json +3 -3
  5. package/.next/cache/webpack/client-production/0.pack +0 -0
  6. package/.next/cache/webpack/client-production/index.pack +0 -0
  7. package/.next/cache/webpack/server-production/0.pack +0 -0
  8. package/.next/cache/webpack/server-production/index.pack +0 -0
  9. package/.next/prerender-manifest.js +1 -1
  10. package/.next/prerender-manifest.json +1 -1
  11. package/.next/react-loadable-manifest.json +3 -2
  12. package/.next/routes-manifest.json +1 -1
  13. package/.next/server/chunks/2778.js +1 -1
  14. package/.next/server/chunks/4365.js +1 -0
  15. package/.next/server/chunks/5244.js +1 -0
  16. package/.next/server/chunks/6011.js +2 -2
  17. package/.next/server/chunks/6886.js +1 -1
  18. package/.next/server/chunks/7692.js +1 -1
  19. package/.next/server/chunks/{7819.js → 8130.js} +1 -6
  20. package/.next/server/chunks/83.js +1 -1
  21. package/.next/server/chunks/{1650.js → 8404.js} +1 -6
  22. package/.next/server/chunks/948.js +2 -2
  23. package/.next/server/chunks/9563.js +2 -2
  24. package/.next/server/functions-config-manifest.json +1 -1
  25. package/.next/server/middleware-build-manifest.js +1 -1
  26. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  27. package/.next/server/pages/404.js.nft.json +1 -1
  28. package/.next/server/pages/500.js.nft.json +1 -1
  29. package/.next/server/pages/[...slug].js +1 -1
  30. package/.next/server/pages/[...slug].js.nft.json +1 -1
  31. package/.next/server/pages/[slug]/p.js +1 -1
  32. package/.next/server/pages/[slug]/p.js.nft.json +1 -1
  33. package/.next/server/pages/_app.js.nft.json +1 -1
  34. package/.next/server/pages/_document.js.nft.json +1 -1
  35. package/.next/server/pages/_error.js.nft.json +1 -1
  36. package/.next/server/pages/account/403.js +1 -1
  37. package/.next/server/pages/account/403.js.nft.json +1 -1
  38. package/.next/server/pages/account/404.js +1 -1
  39. package/.next/server/pages/account/404.js.nft.json +1 -1
  40. package/.next/server/pages/account/[...unknown].js.nft.json +1 -1
  41. package/.next/server/pages/account/orders/[id].js +1 -1
  42. package/.next/server/pages/account/orders/[id].js.nft.json +1 -1
  43. package/.next/server/pages/account/orders.js +1 -1
  44. package/.next/server/pages/account/orders.js.nft.json +1 -1
  45. package/.next/server/pages/account/profile.js +1 -1
  46. package/.next/server/pages/account/profile.js.nft.json +1 -1
  47. package/.next/server/pages/account/security.js +1 -1
  48. package/.next/server/pages/account/security.js.nft.json +1 -1
  49. package/.next/server/pages/account/user-details.js +1 -1
  50. package/.next/server/pages/account/user-details.js.nft.json +1 -1
  51. package/.next/server/pages/account.js +1 -1
  52. package/.next/server/pages/account.js.nft.json +1 -1
  53. package/.next/server/pages/api/graphql.js +2 -2
  54. package/.next/server/pages/api/graphql.js.nft.json +1 -1
  55. package/.next/server/pages/api/health/live.js.nft.json +1 -1
  56. package/.next/server/pages/api/health/ready.js.nft.json +1 -1
  57. package/.next/server/pages/api/preview.js.nft.json +1 -1
  58. package/.next/server/pages/checkout.js.nft.json +1 -1
  59. package/.next/server/pages/en-US/404.html +2 -2
  60. package/.next/server/pages/en-US/500.html +2 -2
  61. package/.next/server/pages/en-US/checkout.html +2 -2
  62. package/.next/server/pages/en-US/login.html +2 -2
  63. package/.next/server/pages/en-US/s.html +2 -2
  64. package/.next/server/pages/en-US.html +2 -2
  65. package/.next/server/pages/index.js.nft.json +1 -1
  66. package/.next/server/pages/login.js.nft.json +1 -1
  67. package/.next/server/pages/s.js.nft.json +1 -1
  68. package/.next/server/pages-manifest.json +1 -1
  69. package/.next/static/chunks/{4803.82e70544e5ad3f13.js → 4803.de5b14237d616808.js} +1 -1
  70. package/.next/static/chunks/4949.ea0775ca3029fb98.js +1 -0
  71. package/.next/static/chunks/{7692.a2ae6dca22038761.js → 7692.1597d1d292a09609.js} +1 -1
  72. package/.next/static/chunks/7861.3fe27a385fea2fb7.js +6 -0
  73. package/.next/static/chunks/9173-c1819846b9006c7a.js +1 -0
  74. package/.next/static/chunks/941.80a0abd58f11d696.js +1 -0
  75. package/.next/static/chunks/pages/{[...slug]-72047653203f9fd2.js → [...slug]-0db18c1c0920e8d2.js} +1 -1
  76. package/.next/static/chunks/pages/_app-1c533ab202b7acef.js +1 -0
  77. package/.next/static/chunks/pages/account/403-c791997011f970b6.js +1 -0
  78. package/.next/static/chunks/pages/account/404-74e64bb12e8f5a68.js +1 -0
  79. package/.next/static/chunks/pages/account/orders/[id]-b9feb0c860ff1cec.js +1 -0
  80. package/.next/static/chunks/pages/account/orders-1d8409a8b4b0e581.js +1 -0
  81. package/.next/static/chunks/pages/account/profile-5a919fa02b76a422.js +1 -0
  82. package/.next/static/chunks/pages/account/security-b5ab3d1ecbbea9d9.js +1 -0
  83. package/.next/static/chunks/pages/account/user-details-6f9fe72e02f5c5df.js +1 -0
  84. package/.next/static/chunks/webpack-a24b8ac1ca628dfe.js +1 -0
  85. package/.next/static/css/32b1696118552960.css +1 -0
  86. package/.next/static/css/{84d35f475d0dc928.css → 831a1f72fe4b2d80.css} +1 -1
  87. package/.next/static/css/ba1d8927d8745656.css +1 -0
  88. package/.next/static/css/e46393a76c5d93a9.css +1 -0
  89. package/.next/static/czdZM7l3yYhwzU9FTEtWh/_buildManifest.js +1 -0
  90. package/.next/trace +131 -129
  91. package/.turbo/turbo-build.log +24 -21
  92. package/.turbo/turbo-test.log +5 -5
  93. package/@generated/gql.ts +14 -6
  94. package/@generated/graphql.ts +372 -5
  95. package/@generated/persisted-documents.json +4 -3
  96. package/@generated/schema.graphql +249 -0
  97. package/CHANGELOG.md +12 -0
  98. package/package.json +6 -4
  99. package/public/icons.svg +26 -0
  100. package/src/components/account/MyAccountDrawer/OrganizationDrawer/OrganizationDrawer.tsx +3 -1
  101. package/src/components/account/MyAccountDrawer/OrganizationDrawer/OrganizationDrawerBody.tsx +12 -2
  102. package/src/components/account/MyAccountDrawer/OrganizationSignInButton/OrganizationSignInButton.tsx +7 -1
  103. package/src/components/account/MyAccountLayout/MyAccountLayout.tsx +12 -2
  104. package/src/components/account/MyAccountMenu/styles.scss +1 -1
  105. package/src/components/account/MyAccountUserDetails/MyAccountUserDetails.tsx +61 -0
  106. package/src/components/account/MyAccountUserDetails/index.ts +1 -0
  107. package/src/components/account/MyAccountUserDetails/styles.module.scss +108 -0
  108. package/src/components/account/components/MyAccountTag/MyAccountTag.tsx +13 -0
  109. package/src/components/account/components/MyAccountTag/index.ts +1 -0
  110. package/src/components/account/components/MyAccountTag/styles.scss +23 -0
  111. package/src/components/account/orders/MyAccountListOrders/MyAccountListOrdersTable/MyAccountListOrdersTable.tsx +5 -5
  112. package/src/components/account/orders/MyAccountListOrders/MyAccountSelectedTags/MyAccountSelectedTags.tsx +16 -4
  113. package/src/components/account/orders/MyAccountOrderDetails/MyAccountBuyingPolicyAlert/MyAccountBuyingPolicyAlert.tsx +153 -0
  114. package/src/components/account/orders/MyAccountOrderDetails/MyAccountBuyingPolicyAlert/index.ts +1 -0
  115. package/src/components/account/orders/MyAccountOrderDetails/MyAccountBuyingPolicyAlert/styles.scss +72 -0
  116. package/src/components/account/orders/MyAccountOrderDetails/MyAccountOrderActionModal/MyAccountOrderActionModal.tsx +41 -88
  117. package/src/components/account/orders/MyAccountOrderDetails/MyAccountOrderActionModal/index.ts +0 -1
  118. package/src/components/account/orders/MyAccountOrderDetails/MyAccountOrderActionModal/styles.module.scss +29 -16
  119. package/src/components/account/orders/MyAccountOrderDetails/MyAccountOrderActions/MyAccountOrderActions.tsx +54 -107
  120. package/src/components/account/orders/MyAccountOrderDetails/MyAccountOrderActions/styles.scss +5 -28
  121. package/src/components/account/orders/MyAccountOrderDetails/MyAccountOrderDetails.tsx +16 -3
  122. package/src/components/account/orders/MyAccountOrderDetails/MyAccountPaymentCard/MyAccountPaymentCard.tsx +1 -3
  123. package/src/components/account/orders/MyAccountOrderDetails/section.module.scss +13 -2
  124. package/src/components/account/profile/i18n.ts +7 -0
  125. package/src/components/account/profile/index.ts +1 -0
  126. package/src/components/account/profile/profile.module.scss +89 -0
  127. package/src/components/account/profile/profile.tsx +63 -0
  128. package/src/components/account/profile/use-date-formatter.ts +25 -0
  129. package/src/components/account/security/SecurityDrawer.tsx +160 -0
  130. package/src/components/account/security/SecuritySection.tsx +45 -0
  131. package/src/components/account/security/index.ts +2 -0
  132. package/src/components/account/security/styles.module.scss +263 -0
  133. package/src/components/navigation/Navbar/Navbar.tsx +4 -1
  134. package/src/components/navigation/NavbarSlider/NavbarSlider.tsx +4 -1
  135. package/src/experimental/myAccountSeverSideProps.ts +9 -0
  136. package/src/pages/account/orders/[id].tsx +61 -5
  137. package/src/pages/account/orders/index.tsx +14 -2
  138. package/src/pages/account/profile.tsx +31 -5
  139. package/src/pages/account/security.tsx +15 -4
  140. package/src/pages/account/user-details.tsx +54 -17
  141. package/src/sdk/account/getIsRepresentative.ts +20 -0
  142. package/src/sdk/account/getMyAccountRoutes.ts +17 -13
  143. package/src/sdk/account/useOrderAuthorization.ts +79 -0
  144. package/src/utils/getCookie.ts +7 -0
  145. package/src/utils/userOrderStatus.ts +4 -0
  146. package/test/server/index.test.ts +3 -0
  147. package/.next/server/chunks/2570.js +0 -1
  148. package/.next/server/chunks/941.js +0 -1
  149. package/.next/static/_fNL5rUsrvwdHfkRr9RdO/_buildManifest.js +0 -1
  150. package/.next/static/chunks/4949.58cc42cd6109f59a.js +0 -6
  151. package/.next/static/chunks/9173-94386b70c1626a31.js +0 -1
  152. package/.next/static/chunks/941.6fb7ccae2268ce5d.js +0 -1
  153. package/.next/static/chunks/pages/_app-c3dce4c45c6c6b35.js +0 -1
  154. package/.next/static/chunks/pages/account/403-6f4addf9a9d54a1c.js +0 -1
  155. package/.next/static/chunks/pages/account/404-9e8ca6ee5f981dae.js +0 -1
  156. package/.next/static/chunks/pages/account/orders/[id]-0780c7252aa3283f.js +0 -1
  157. package/.next/static/chunks/pages/account/orders-6aad8b35fc95ce57.js +0 -1
  158. package/.next/static/chunks/pages/account/profile-adfe3518bdab5463.js +0 -1
  159. package/.next/static/chunks/pages/account/security-ea5c8811b3e6e415.js +0 -1
  160. package/.next/static/chunks/pages/account/user-details-9309d14f4e59f398.js +0 -1
  161. package/.next/static/chunks/webpack-c76f1cac87402029.js +0 -1
  162. package/.next/static/css/506442c818624bd2.css +0 -1
  163. package/src/components/account/orders/MyAccountOrderDetails/MyAccountOrderActionModal/useOrderActionModal.ts +0 -38
  164. package/src/sdk/account/useApproveOrder.ts +0 -53
  165. package/src/sdk/account/useRejectOrder.ts +0 -53
  166. /package/.next/static/{_fNL5rUsrvwdHfkRr9RdO → czdZM7l3yYhwzU9FTEtWh}/_ssgManifest.js +0 -0
@@ -0,0 +1,108 @@
1
+ @layer components {
2
+ .section {
3
+ @import "../components/MyAccountTag/styles.scss";
4
+
5
+ // --------------------------------------------------------
6
+ // Design Tokens
7
+ // --------------------------------------------------------
8
+
9
+ --fs-user-details-padding : var(--fs-spacing-4) var(--fs-spacing-9);
10
+
11
+ // Title
12
+ --fs-user-details-title-padding : var(--fs-spacing-4) 0;
13
+ --fs-user-details-title-size : var(--fs-text-size-4);
14
+ --fs-user-details-title-weight : var(--fs-text-weight-semibold);
15
+ --fs-user-details-title-line-height : var(--fs-spacing-4);
16
+
17
+ // Divider
18
+ --fs-user-details-divider-border : calc(var(--fs-border-width) / 2) solid #e0e0e0;
19
+
20
+ // Row
21
+ --fs-user-details-row-padding : var(--fs-spacing-4) 0;
22
+ --fs-user-details-row-weight : var(--fs-text-weight-medium);
23
+ --fs-user-details-row-label-width : 12.5rem;
24
+ --fs-user-details-row-label-size : var(--fs-text-size-1);
25
+ --fs-user-details-row-label-weight : var(--fs-text-weight-medium);
26
+ --fs-user-details-row-label-color : var(--fs-color-neutral-5);
27
+
28
+ // Row Value
29
+ --fs-user-details-row-value-size : var(--fs-text-size-1);
30
+ --fs-user-details-row-value-weight : var(--fs-text-weight-medium);
31
+ --fs-user-details-row-value-color : black;
32
+
33
+ width: 100%;
34
+ padding: var(--fs-user-details-padding);
35
+
36
+ @include media("<notebook") {
37
+ padding: var(--fs-spacing-0) var(--fs-spacing-5);
38
+ }
39
+
40
+ [data-fs-user-details-table] {
41
+ width: 100%;
42
+ border-spacing: 0;
43
+ border-collapse: collapse;
44
+ }
45
+
46
+ [data-fs-user-details-row] {
47
+ display: flex;
48
+ padding: var(--fs-user-details-row-padding);
49
+ font-weight: var(--fs-user-details-row-weight);
50
+ line-height: var(--fs-user-details-row-line-height);
51
+ border-bottom: var(--fs-user-details-divider-border);
52
+
53
+ @include media("<tablet") {
54
+ flex-direction: column;
55
+ gap: .5rem;
56
+ }
57
+ }
58
+
59
+ [data-fs-user-details-row]:last-of-type {
60
+ border-bottom: none;
61
+ }
62
+
63
+ [data-fs-user-details-divider-row] {
64
+ height: 0;
65
+ }
66
+
67
+ [data-fs-user-details-divider] {
68
+ height: 0;
69
+ padding: 0;
70
+ border: none;
71
+ border: var(--fs-user-details-divider-border);
72
+ }
73
+
74
+ [data-fs-user-details-title] {
75
+ display: flex;
76
+ align-items: center;
77
+ justify-content: space-between;
78
+ padding: var(--fs-user-details-title-padding);
79
+ font-size: var(--fs-user-details-title-size);
80
+ font-weight: var(--fs-user-details-title-weight);
81
+ line-height: var(--fs-user-details-title-line-height);
82
+ }
83
+
84
+ [data-fs-user-details-row-label] {
85
+ width: var(--fs-user-details-row-label-width);
86
+ font-size: var(--fs-user-details-row-label-size);
87
+ font-weight: var(--fs-user-details-row-label-weight);
88
+ color: var(--fs-user-details-row-label-color);
89
+ text-align: left;
90
+ }
91
+
92
+ [data-fs-user-details-row-value] {
93
+ font-size: var(--fs-user-details-row-value-size);
94
+ font-weight: var(--fs-user-details-row-value-weight);
95
+ color: var(--fs-user-details-row-value-color);
96
+ }
97
+
98
+ [data-fs-user-details-row-tags] {
99
+ display: flex;
100
+ flex-wrap: wrap;
101
+ gap: var(--fs-spacing-0);
102
+
103
+ [data-fs-user-details-row-value] {
104
+ margin-top: var(--fs-spacing-0);
105
+ }
106
+ }
107
+ }
108
+ }
@@ -0,0 +1,13 @@
1
+ import type { ReactNode } from 'react'
2
+
3
+ export type TagProps = {
4
+ children: ReactNode
5
+ }
6
+
7
+ const Tag = ({ children, ...otherProps }: TagProps) => (
8
+ <span data-fs-tag {...otherProps}>
9
+ {children}
10
+ </span>
11
+ )
12
+
13
+ export default Tag
@@ -0,0 +1 @@
1
+ export { default } from './MyAccountTag'
@@ -0,0 +1,23 @@
1
+ [data-fs-tag] {
2
+ // --------------------------------------------------------
3
+ // Design Tokens
4
+ // --------------------------------------------------------
5
+
6
+ --fs-tag-padding : var(--fs-spacing-0) var(--fs-spacing-2);
7
+ --fs-tag-font-size : var(--fs-text-size-0);
8
+ --fs-tag-font-weight : var(--fs-text-weight-regular);
9
+ --fs-tag-line-height : var(--fs-spacing-3);
10
+ --fs-tag-color : black;
11
+ --fs-tag-bkg-color : #f5f5f5;
12
+ --fs-tag-radius : var(--fs-border-radius-pill);
13
+
14
+ padding: var(--fs-tag-padding);
15
+ margin-right: var(--fs-spacing-0);
16
+ font-size: var(--fs-tag-font-size);
17
+ font-weight: var(--fs-tag-font-weight);
18
+ line-height: var(--fs-tag-line-height);
19
+ color: var(--fs-tag-color);
20
+ white-space: nowrap;
21
+ background-color: var(--fs-tag-bkg-color);
22
+ border-radius: var(--fs-tag-radius);
23
+ }
@@ -10,7 +10,7 @@ import useScreenResize from 'src/sdk/ui/useScreenResize'
10
10
 
11
11
  const MAX_COST_CENTERS = 5
12
12
 
13
- function formatShippingDate(date: string, locale: string) {
13
+ function formatOrderDate(date: string, locale: string) {
14
14
  return new Date(date).toLocaleDateString(locale, {
15
15
  year: 'numeric',
16
16
  month: '2-digit',
@@ -180,7 +180,7 @@ export default function MyAccountListOrdersTable({
180
180
  </p>
181
181
  <p data-fs-list-orders-table-product-info-value>
182
182
  {item.creationDate
183
- ? formatShippingDate(item.creationDate, locale)
183
+ ? formatOrderDate(item.creationDate, locale)
184
184
  : '-'}
185
185
  </p>
186
186
  </div>
@@ -192,7 +192,7 @@ export default function MyAccountListOrdersTable({
192
192
  </p>
193
193
  <p data-fs-list-orders-table-product-info-value>
194
194
  {item.ShippingEstimatedDate
195
- ? formatShippingDate(
195
+ ? formatOrderDate(
196
196
  item.ShippingEstimatedDate,
197
197
  locale
198
198
  )
@@ -222,7 +222,7 @@ export default function MyAccountListOrdersTable({
222
222
  </p>
223
223
  <p data-fs-list-orders-table-product-info-value>
224
224
  {item.ShippingEstimatedDate
225
- ? formatShippingDate(
225
+ ? formatOrderDate(
226
226
  item.ShippingEstimatedDate,
227
227
  locale
228
228
  )
@@ -317,7 +317,7 @@ export default function MyAccountListOrdersTable({
317
317
  {!isDesktop && (
318
318
  <p>
319
319
  {item.ShippingEstimatedDate
320
- ? `Delivery by ${formatShippingDate(
320
+ ? `Delivery by ${formatOrderDate(
321
321
  item.ShippingEstimatedDate,
322
322
  locale
323
323
  )}`
@@ -15,8 +15,20 @@ type MyAccountSelectedTagsProps = {
15
15
  ) => void
16
16
  }
17
17
 
18
- function formatShippingDate(date: string, locale: string) {
19
- return new Date(date).toLocaleDateString(locale, {
18
+ /**
19
+ * This function formats the shipping date to a localized string. To avoid timezone issues, it parses the date string manually.
20
+ * @param date - Example date input: "2023-10-01" (YYYY-MM-DD)
21
+ * @param locale - The locale to format the date string, e.g., 'en-US', 'pt-BR'.
22
+ * @returns Formatted date string in the format "MM/DD/YYYY" or "DD/MM/YYYY" depending on the locale.
23
+ */
24
+ function formatFilterDate(date: string, locale: string) {
25
+ // Parse the date string manually to avoid timezone issues
26
+ const [year, month, day] = date.split('-').map(Number)
27
+
28
+ // Create date object using local timezone (not UTC)
29
+ const dateObj = new Date(year, month - 1, day)
30
+
31
+ return dateObj.toLocaleDateString(locale, {
20
32
  year: 'numeric',
21
33
  month: '2-digit',
22
34
  day: '2-digit',
@@ -30,10 +42,10 @@ function Tags({
30
42
  const { locale } = useSession()
31
43
  const { dateInitial, dateFinal, status } = filters
32
44
  const formattedDateInitial = dateInitial
33
- ? formatShippingDate(dateInitial, locale)
45
+ ? formatFilterDate(dateInitial, locale)
34
46
  : ''
35
47
  const formattedDateFinal = dateFinal
36
- ? formatShippingDate(dateFinal, locale)
48
+ ? formatFilterDate(dateFinal, locale)
37
49
  : ''
38
50
 
39
51
  const dateTag = (dateInitial || dateFinal) && (
@@ -0,0 +1,153 @@
1
+ import {
2
+ Alert as UIAlert,
3
+ Button as UIButton,
4
+ Icon as UIIcon,
5
+ useUI,
6
+ } from '@faststore/ui'
7
+ import { useState } from 'react'
8
+ import MyAccountOrderActionModal from '../MyAccountOrderActionModal'
9
+ import { useOrderAuthorization } from 'src/sdk/account/useOrderAuthorization'
10
+ import type { ProcessOrderAuthorizationRule } from '@generated/graphql'
11
+
12
+ interface MyAccountBuyingPolicyAlertProps {
13
+ ruleForAuthorization: ProcessOrderAuthorizationRule
14
+ onAuthorizationComplete?: () => void
15
+ }
16
+
17
+ export default function MyAccountBuyingPolicyAlert({
18
+ ruleForAuthorization,
19
+ onAuthorizationComplete,
20
+ }: MyAccountBuyingPolicyAlertProps) {
21
+ const { pushToast } = useUI()
22
+ const [isAuthorizationOpen, setIsAuthorizationOpen] = useState<boolean>(false)
23
+ const { data, error, processOrderAuthorization, loading } =
24
+ useOrderAuthorization()
25
+
26
+ const handleApprove = async () => {
27
+ try {
28
+ await processOrderAuthorization({
29
+ data: {
30
+ orderAuthorizationId: ruleForAuthorization.orderAuthorizationId,
31
+ ruleId: ruleForAuthorization.rule.id,
32
+ dimensionId: ruleForAuthorization.dimensionId,
33
+ approved: true,
34
+ },
35
+ })
36
+
37
+ // Success toast
38
+ pushToast({
39
+ status: 'INFO',
40
+ message: `${ruleForAuthorization.rule.name} policy approved successfully.`,
41
+ icon: <UIIcon width={30} height={30} name="CircleWavyCheck" />,
42
+ })
43
+
44
+ onAuthorizationComplete?.()
45
+ } catch (error) {
46
+ pushToast({
47
+ status: 'ERROR',
48
+ message: "Policy couldn't be approved due to a technical issue.",
49
+ icon: <UIIcon width={30} height={30} name="CircleWavyWarning" />,
50
+ })
51
+ }
52
+ }
53
+
54
+ const handleReject = async () => {
55
+ try {
56
+ await processOrderAuthorization({
57
+ data: {
58
+ orderAuthorizationId: ruleForAuthorization.orderAuthorizationId,
59
+ ruleId: ruleForAuthorization.rule.id,
60
+ dimensionId: ruleForAuthorization.dimensionId,
61
+ approved: false,
62
+ },
63
+ })
64
+
65
+ pushToast({
66
+ status: 'INFO',
67
+ message: `${ruleForAuthorization.rule.name} policy rejected successfully. Order denied.`,
68
+ icon: <UIIcon width={30} height={30} name="XCircle" />,
69
+ })
70
+
71
+ setIsAuthorizationOpen(false)
72
+ onAuthorizationComplete?.()
73
+ } catch (error) {
74
+ pushToast({
75
+ status: 'ERROR',
76
+ message: "Policy couldn't be rejected due to a technical issue.",
77
+ icon: <UIIcon width={30} height={30} name="CircleWavyWarning" />,
78
+ })
79
+ }
80
+ }
81
+
82
+ if (!ruleForAuthorization) {
83
+ return null
84
+ }
85
+
86
+ return (
87
+ <>
88
+ <div data-fs-buying-policy-alert>
89
+ <div data-fs-buying-policy-message>
90
+ <h3 data-fs-buying-policy-title>{ruleForAuthorization.rule.name}</h3>
91
+ <p data-fs-buying-policy-description>
92
+ This buying policy requires your approval before the order can
93
+ proceed.
94
+ </p>
95
+ </div>
96
+
97
+ <div data-fs-buying-policy-actions>
98
+ <UIButton
99
+ variant="secondary"
100
+ size="small"
101
+ icon={<UIIcon name="XCircle" />}
102
+ onClick={() => setIsAuthorizationOpen(true)}
103
+ disabled={loading}
104
+ data-fs-buying-policy-action-reject
105
+ data-fs-button-danger
106
+ >
107
+ Reject
108
+ </UIButton>
109
+ <UIButton
110
+ variant="primary"
111
+ size="small"
112
+ icon={<UIIcon name="CircleCheck" />}
113
+ onClick={handleApprove}
114
+ loading={loading}
115
+ data-fs-buying-policy-action-approve
116
+ >
117
+ Approve
118
+ </UIButton>
119
+ </div>
120
+ </div>
121
+
122
+ {data?.isPendingForOtherAuthorizer && (
123
+ <UIAlert
124
+ data-fs-pending-policies-alert
125
+ icon={<UIIcon name="Info" width={20} height={20} />}
126
+ >
127
+ Your approval is recorded. This order is still pending further
128
+ approvals.
129
+ </UIAlert>
130
+ )}
131
+
132
+ <MyAccountOrderActionModal
133
+ isOpen={isAuthorizationOpen}
134
+ loading={loading}
135
+ onClose={() => setIsAuthorizationOpen(false)}
136
+ onConfirm={handleReject}
137
+ title="Reject approval request"
138
+ message={
139
+ <>
140
+ You're about to reject this approval request, triggered by the
141
+ {` ${ruleForAuthorization.rule.name} policy`}. Rejecting any
142
+ approval request will deny the entire order.
143
+ <br />
144
+ <br />
145
+ This action is permanent and cannot be undone.
146
+ </>
147
+ }
148
+ confirmText="Reject"
149
+ danger
150
+ />
151
+ </>
152
+ )
153
+ }
@@ -0,0 +1 @@
1
+ export { default } from './MyAccountBuyingPolicyAlert'
@@ -0,0 +1,72 @@
1
+ [data-fs-buying-policy-alert] {
2
+ // --------------------------------------------------------
3
+ // Design Tokens
4
+ // --------------------------------------------------------
5
+
6
+ // Default properties
7
+ --fs-buying-policy-card-padding : var(--fs-spacing-3);
8
+ --fs-buying-policy-card-gap : var(--fs-spacing-0);
9
+ --fs-buying-policy-card-border-radius : var(--fs-border-radius);
10
+ --fs-buying-policy-card-bkg : #fdf5e9;
11
+
12
+ // Message
13
+ --fs-buying-policy-title-size : var(--fs-text-size-2);
14
+ --fs-buying-policy-title-weight : var(--fs-text-weight-semibold);
15
+ --fs-buying-policy-title-line-height : 1.5;
16
+ --fs-buying-policy-description-size : var(--fs-text-size-1);
17
+ --fs-buying-policy-description-line-height: 1.43;
18
+ --fs-buying-policy-description-color : var(--fs-color-text-light);
19
+
20
+ // Pending policies alert
21
+ --fs-pending-policies-alert-bkg : #e1f3ff;
22
+
23
+ // --------------------------------------------------------
24
+ // Structural Styles
25
+ // --------------------------------------------------------
26
+
27
+ display: flex;
28
+ flex-flow: row wrap;
29
+ gap: var(--fs-buying-policy-card-gap);
30
+ justify-content: space-between;
31
+ padding: var(--fs-buying-policy-card-padding);
32
+ background: var(--fs-buying-policy-card-bkg);
33
+ border-radius: var(--fs-buying-policy-card-border-radius);
34
+
35
+ [data-fs-button-icon] {
36
+ flex-shrink: 0;
37
+ }
38
+
39
+ [data-fs-buying-policy-message] {
40
+ [data-fs-buying-policy-title] {
41
+ font-size: var(--fs-buying-policy-title-size);
42
+ font-weight: var(--fs-buying-policy-title-weight);
43
+ line-height: var(--fs-buying-policy-title-line-height);
44
+ color: var(--fs-color-text);
45
+ }
46
+
47
+ [data-fs-buying-policy-description] {
48
+ font-size: var(--fs-buying-policy-description-size);
49
+ line-height: var(--fs-buying-policy-description-line-height);
50
+ color: var(--fs-buying-policy-description-color);
51
+ }
52
+ }
53
+
54
+ [data-fs-buying-policy-actions] {
55
+ display: flex;
56
+ align-items: flex-start;
57
+
58
+ [data-fs-buying-policy-action-reject] {
59
+ --fs-button-secondary-text-color: var(--fs-color-danger-text);
60
+ --fs-button-secondary-bkg-color-hover: var(--fs-button-secondary-text-color);
61
+ }
62
+ }
63
+
64
+ [data-fs-buying-policy-alert] {
65
+ grid-column: span 2;
66
+ }
67
+
68
+ [data-fs-pending-policies-alert] {
69
+ grid-column: span 2;
70
+ background: var(--fs-pending-policies-alert-bkg);
71
+ }
72
+ }
@@ -4,118 +4,71 @@ import {
4
4
  ModalBody as UIModalBody,
5
5
  ModalFooter as UIModalFooter,
6
6
  Button as UIButton,
7
+ type ButtonProps,
8
+ useFadeEffect,
7
9
  } from '@faststore/ui'
8
- import useScreenResize from 'src/sdk/ui/useScreenResize'
9
- import BottomSheet from 'src/components/account/components/BottomSheet/BottomSheet'
10
10
  import styles from './styles.module.scss'
11
11
 
12
- export type OrderActionType = 'cancel' | 'reject' | 'approve'
13
-
14
- interface OrderActionConfig {
15
- title: string
16
- message: string
17
- confirmText: string
18
- cancelText: string
19
- confirmVariant: 'primary' | 'secondary' | 'tertiary'
20
- }
21
-
22
- const ACTION_CONFIGS: Record<OrderActionType, OrderActionConfig> = {
23
- cancel: {
24
- title: 'Cancel order',
25
- message:
26
- "Are you sure you want to cancel this order? This action can't be undone.",
27
- confirmText: 'Cancel order',
28
- cancelText: 'Not now',
29
- confirmVariant: 'secondary',
30
- },
31
- reject: {
32
- title: 'Reject order',
33
- message:
34
- "Are you sure you want to reject this order? This action can't be undone.",
35
- confirmText: 'Reject',
36
- cancelText: 'Cancel',
37
- confirmVariant: 'primary',
38
- },
39
- approve: {
40
- title: 'Approve order',
41
- message: 'Are you sure you want to approve this order?',
42
- confirmText: 'Approve',
43
- cancelText: 'Cancel',
44
- confirmVariant: 'primary',
45
- },
46
- }
47
-
48
12
  interface MyAccountOrderActionModalProps {
49
13
  isOpen: boolean
50
14
  loading?: boolean
51
- fade?: 'in' | 'out'
52
- actionType: OrderActionType | null
53
- onClose: (actionType: OrderActionType) => void
54
- onConfirm: (actionType: OrderActionType) => void
15
+ title: string
16
+ message: React.ReactNode
17
+ confirmText: string
18
+ cancelText?: string
19
+ confirmVariant?: ButtonProps['variant']
20
+ danger?: boolean
21
+ onClose: () => void
22
+ onConfirm: () => void
55
23
  }
56
24
 
57
25
  export default function MyAccountOrderActionModal({
58
26
  isOpen = false,
59
27
  loading = false,
60
- fade = 'out',
61
- actionType,
28
+ title,
29
+ message,
30
+ confirmText,
31
+ cancelText = 'Not now',
32
+ confirmVariant = 'primary',
33
+ danger = false,
62
34
  onClose,
63
35
  onConfirm,
64
36
  }: MyAccountOrderActionModalProps) {
65
- const { isMobile, isTablet } = useScreenResize()
37
+ const { fade, fadeOut, fadeIn } = useFadeEffect()
66
38
 
67
- const config: OrderActionConfig | null =
68
- actionType && ACTION_CONFIGS[actionType]
69
- const dialogContent = (
70
- <>
71
- <UIModalHeader
72
- title={config?.title}
73
- onClose={() => onClose(actionType)}
74
- />
39
+ return (
40
+ <UIModal
41
+ data-fs-order-details-action-modal
42
+ isOpen={isOpen}
43
+ onDismiss={fadeOut}
44
+ onTransitionEnd={() => {
45
+ if (fade === 'out') {
46
+ onClose()
47
+ fadeIn()
48
+ }
49
+ }}
50
+ overlayProps={{
51
+ className: styles.orderActionsModal,
52
+ }}
53
+ data-fs-modal-state={fade}
54
+ >
55
+ <UIModalHeader title={title} onClose={fadeOut} />
75
56
  <UIModalBody>
76
- <p data-fs-order-details-action-modal-message>{config?.message}</p>
57
+ <p data-fs-order-details-action-modal-message>{message}</p>
77
58
  </UIModalBody>
78
59
  <UIModalFooter>
79
- <UIButton variant="tertiary" onClick={() => onClose(actionType)}>
80
- {config?.cancelText}
60
+ <UIButton variant="secondary" onClick={fadeOut} disabled={loading}>
61
+ {cancelText}
81
62
  </UIButton>
82
63
  <UIButton
83
- variant={config?.confirmVariant}
84
- onClick={() => onConfirm(actionType)}
64
+ variant={confirmVariant}
65
+ onClick={onConfirm}
85
66
  loading={loading}
67
+ data-fs-button-danger={danger}
86
68
  >
87
- {config?.confirmText}
69
+ {confirmText}
88
70
  </UIButton>
89
71
  </UIModalFooter>
90
- </>
91
- )
92
-
93
- if (isMobile || isTablet) {
94
- return (
95
- <BottomSheet
96
- data-fs-order-details-action-modal
97
- isOpen={isOpen}
98
- onDismiss={() => onClose(actionType)}
99
- fade={fade}
100
- overlayProps={{
101
- className: styles.orderActionsModal,
102
- }}
103
- >
104
- {dialogContent}
105
- </BottomSheet>
106
- )
107
- }
108
-
109
- return (
110
- <UIModal
111
- data-fs-order-details-action-modal
112
- isOpen={isOpen}
113
- onDismiss={() => onClose(actionType)}
114
- overlayProps={{
115
- className: styles.orderActionsModal,
116
- }}
117
- >
118
- {dialogContent}
119
72
  </UIModal>
120
73
  )
121
74
  }
@@ -1,2 +1 @@
1
1
  export { default } from './MyAccountOrderActionModal'
2
- export { useOrderActionModal } from './useOrderActionModal'
@@ -7,34 +7,47 @@
7
7
  @import "src/components/account/components/BottomSheet/styles.scss";
8
8
 
9
9
  [data-fs-order-details-action-modal] {
10
+ [data-fs-modal-header] {
11
+ [data-fs-modal-header-title] {
12
+ margin: 0;
13
+ font-size: var(--fs-text-size-lead);
14
+ font-weight: var(--fs-text-weight-medium);
15
+ line-height: 1.56;
16
+ }
17
+ }
18
+
10
19
  [data-fs-modal-body] {
11
20
  [data-fs-order-details-action-modal-message] {
12
- font-size: var(--fs-text-size-body);
13
- line-height: 1.5;
21
+ font-size: var(--fs-text-size-2);
22
+ line-height: 1.25;
14
23
  color: var(--fs-color-text);
15
24
  }
16
25
  }
17
26
 
18
27
  [data-fs-modal-footer] {
19
- @include media("<=tablet") {
20
- padding: var(--fs-spacing-3) 0 var(--fs-spacing-3);
28
+ padding: var(--fs-spacing-3) var(--fs-spacing-4);
21
29
 
22
- [data-fs-modal-footer-actions] {
23
- display: flex;
24
- flex-flow: row wrap;
25
- gap: var(--fs-spacing-3);
26
- align-items: center;
27
- justify-content: flex-end;
28
- max-width: 25rem;
29
- padding: var(--fs-spacing-1) var(--fs-spacing-4);
30
- margin-left: auto;
30
+ [data-fs-modal-footer-actions] {
31
+ display: flex;
32
+ flex-flow: row wrap;
33
+ gap: var(--fs-spacing-3);
34
+ align-items: center;
35
+ padding: 0;
31
36
 
32
- > * {
33
- flex-grow: 1;
34
- }
37
+ > * {
38
+ flex-grow: 1;
35
39
  }
36
40
  }
37
41
  }
38
42
  }
43
+
44
+ [data-fs-button-danger] {
45
+ --fs-button-secondary-text-color: var(--fs-color-danger-text);
46
+ --fs-button-secondary-bkg-color-hover: var(--fs-button-secondary-text-color);
47
+ --fs-button-tertiary-text-color: var(--fs-color-danger-text);
48
+ --fs-button-primary-bkg-color: var(--fs-color-danger-text);
49
+ --fs-button-primary-bkg-color-hover: var(--fs-button-primary-bkg-color);
50
+ --fs-button-primary-bkg-color-active: var(--fs-button-primary-bkg-color);
51
+ }
39
52
  }
40
53
  }