@open-mercato/core 0.6.2-develop.3372.1.de9a169973 → 0.6.2-develop.3380.1.bb14509041
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/dist/modules/sales/api/order-adjustments/route.js +2 -2
- package/dist/modules/sales/api/order-adjustments/route.js.map +2 -2
- package/dist/modules/sales/api/quote-adjustments/route.js +2 -2
- package/dist/modules/sales/api/quote-adjustments/route.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +3 -3
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/data/validators.js +61 -6
- package/dist/modules/sales/data/validators.js.map +2 -2
- package/dist/modules/sales/lib/calculations.js +6 -3
- package/dist/modules/sales/lib/calculations.js.map +2 -2
- package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js +84 -62
- package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/notifications/i18n/de.json +6 -1
- package/src/modules/notifications/i18n/en.json +6 -1
- package/src/modules/notifications/i18n/es.json +6 -1
- package/src/modules/notifications/i18n/pl.json +6 -1
- package/src/modules/sales/api/order-adjustments/route.ts +2 -2
- package/src/modules/sales/api/quote-adjustments/route.ts +2 -2
- package/src/modules/sales/commands/documents.ts +3 -3
- package/src/modules/sales/data/validators.ts +78 -9
- package/src/modules/sales/lib/calculations.ts +16 -3
- package/src/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.tsx +87 -69
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
3
|
import * as React from 'react'
|
|
4
|
-
import { ShoppingCart, ExternalLink,
|
|
4
|
+
import { ShoppingCart, ExternalLink, Loader2, X } from 'lucide-react'
|
|
5
5
|
import { useRouter } from 'next/navigation'
|
|
6
6
|
import { Button } from '@open-mercato/ui/primitives/button'
|
|
7
|
+
import { IconButton } from '@open-mercato/ui/primitives/icon-button'
|
|
7
8
|
import { cn } from '@open-mercato/shared/lib/utils'
|
|
8
9
|
import { formatRelativeTime } from '@open-mercato/shared/lib/time'
|
|
9
10
|
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
@@ -56,11 +57,13 @@ export function SalesOrderCreatedRenderer({
|
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
|
|
60
|
+
const timeAgo = formatRelativeTime(notification.createdAt, { translate: t }) ?? ''
|
|
61
|
+
|
|
59
62
|
return (
|
|
60
63
|
<div
|
|
61
64
|
className={cn(
|
|
62
|
-
'group relative
|
|
63
|
-
isUnread && 'bg-
|
|
65
|
+
'group relative flex gap-4 items-start rounded-xl p-3 transition-colors hover:bg-muted/40 cursor-pointer',
|
|
66
|
+
isUnread && 'bg-muted/20',
|
|
64
67
|
)}
|
|
65
68
|
onClick={handleView}
|
|
66
69
|
onKeyDown={(e) => {
|
|
@@ -72,77 +75,92 @@ export function SalesOrderCreatedRenderer({
|
|
|
72
75
|
role="button"
|
|
73
76
|
tabIndex={0}
|
|
74
77
|
>
|
|
75
|
-
{
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
78
|
+
{/* Avatar: indigo-tinted circle with shopping-cart icon */}
|
|
79
|
+
<div className="relative shrink-0 flex size-10 items-center justify-center rounded-full bg-status-info-bg">
|
|
80
|
+
<ShoppingCart className="size-5 text-status-info-icon" aria-hidden="true" />
|
|
81
|
+
{isUnread ? (
|
|
82
|
+
<span
|
|
83
|
+
className="absolute -right-1 -top-1 size-3 rounded-full bg-accent-indigo ring-2 ring-background"
|
|
84
|
+
aria-hidden="true"
|
|
85
|
+
/>
|
|
86
|
+
) : null}
|
|
87
|
+
</div>
|
|
85
88
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
</h4>
|
|
92
|
-
{orderNumber && (
|
|
93
|
-
<div className="flex items-center gap-1 mt-0.5">
|
|
94
|
-
<span className="text-xs font-mono text-muted-foreground bg-muted px-1.5 py-0.5 rounded">
|
|
95
|
-
#{orderNumber}
|
|
96
|
-
</span>
|
|
97
|
-
</div>
|
|
98
|
-
)}
|
|
99
|
-
</div>
|
|
100
|
-
<span className="flex-shrink-0 text-xs text-muted-foreground flex items-center gap-1">
|
|
101
|
-
<Calendar className="h-3 w-3" />
|
|
102
|
-
{formatRelativeTime(notification.createdAt, { translate: t }) ?? ''}
|
|
103
|
-
</span>
|
|
104
|
-
</div>
|
|
89
|
+
<div className="flex min-w-0 flex-1 flex-col gap-1">
|
|
90
|
+
{/* Title row */}
|
|
91
|
+
<p className="truncate text-sm font-medium leading-5 tracking-tight text-foreground">
|
|
92
|
+
{notification.title}
|
|
93
|
+
</p>
|
|
105
94
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
95
|
+
{/* Description row: time · order# · total · assigned — inline so it wraps naturally per line */}
|
|
96
|
+
<div className="text-xs leading-4 text-muted-foreground">
|
|
97
|
+
{timeAgo ? (
|
|
98
|
+
<>
|
|
99
|
+
<span className="whitespace-nowrap">{timeAgo}</span>
|
|
100
|
+
<span aria-hidden="true" className="mx-1 text-text-disabled">·</span>
|
|
101
|
+
</>
|
|
102
|
+
) : null}
|
|
103
|
+
{orderNumber ? (
|
|
104
|
+
<>
|
|
105
|
+
<span className="inline-flex items-center rounded bg-muted px-1.5 py-0.5 font-mono text-overline text-foreground">
|
|
106
|
+
#{orderNumber}
|
|
107
|
+
</span>
|
|
108
|
+
<span aria-hidden="true" className="mx-1 text-text-disabled">·</span>
|
|
109
|
+
</>
|
|
110
|
+
) : null}
|
|
111
|
+
{currentTotal ? (
|
|
112
|
+
<>
|
|
113
|
+
<span className="whitespace-nowrap font-medium text-foreground">{currentTotal}</span>
|
|
114
|
+
<span aria-hidden="true" className="mx-1 text-text-disabled">·</span>
|
|
115
|
+
</>
|
|
116
|
+
) : null}
|
|
117
|
+
<span className="whitespace-nowrap">{t('sales.notifications.renderer.assignedToYou', 'Assigned to you')}</span>
|
|
118
|
+
</div>
|
|
118
119
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
<
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
120
|
+
{/* Actions row */}
|
|
121
|
+
<div className="mt-2 flex items-center gap-2">
|
|
122
|
+
<Button
|
|
123
|
+
type="button"
|
|
124
|
+
size="sm"
|
|
125
|
+
className="h-8 rounded-md px-2.5 bg-accent-indigo text-accent-indigo-foreground hover:bg-accent-indigo/90"
|
|
126
|
+
onClick={(e) => {
|
|
127
|
+
e.stopPropagation()
|
|
128
|
+
handleView()
|
|
129
|
+
}}
|
|
130
|
+
disabled={executing || (!viewAction && !notification.linkHref)}
|
|
131
|
+
>
|
|
132
|
+
<ExternalLink className="size-3.5" aria-hidden="true" />
|
|
133
|
+
{t('sales.notifications.renderer.viewOrder', 'View Order')}
|
|
134
|
+
{executing ? <Loader2 className="ml-1 size-3 animate-spin" /> : null}
|
|
135
|
+
</Button>
|
|
136
|
+
<Button
|
|
137
|
+
type="button"
|
|
138
|
+
variant="outline"
|
|
139
|
+
size="sm"
|
|
140
|
+
className="h-8 rounded-md px-2.5"
|
|
141
|
+
onClick={(e) => {
|
|
142
|
+
e.stopPropagation()
|
|
143
|
+
onDismiss()
|
|
144
|
+
}}
|
|
145
|
+
>
|
|
146
|
+
{t('notifications.actions.dismiss', 'Dismiss')}
|
|
147
|
+
</Button>
|
|
144
148
|
</div>
|
|
145
149
|
</div>
|
|
150
|
+
|
|
151
|
+
<IconButton
|
|
152
|
+
type="button"
|
|
153
|
+
variant="ghost"
|
|
154
|
+
size="xs"
|
|
155
|
+
className="absolute right-2 top-2 opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100"
|
|
156
|
+
onClick={(e) => {
|
|
157
|
+
e.stopPropagation()
|
|
158
|
+
onDismiss()
|
|
159
|
+
}}
|
|
160
|
+
aria-label={t('notifications.actions.dismiss', 'Dismiss')}
|
|
161
|
+
>
|
|
162
|
+
<X className="size-3.5" />
|
|
163
|
+
</IconButton>
|
|
146
164
|
</div>
|
|
147
165
|
)
|
|
148
166
|
}
|