@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.
@@ -1,9 +1,10 @@
1
1
  'use client'
2
2
 
3
3
  import * as React from 'react'
4
- import { ShoppingCart, ExternalLink, DollarSign, User, Calendar } from 'lucide-react'
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 px-4 py-3 hover:bg-muted/50 cursor-pointer transition-colors border-l-4 border-l-status-info-border',
63
- isUnread && 'bg-status-info-bg/50'
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
- {isUnread && (
76
- <div className="absolute left-1.5 top-1/2 -translate-y-1/2 h-2 w-2 rounded-full bg-primary" />
77
- )}
78
-
79
- <div className="flex gap-3">
80
- <div className="flex-shrink-0 mt-0.5">
81
- <div className="h-10 w-10 rounded-lg bg-status-info-bg flex items-center justify-center">
82
- <ShoppingCart className="h-5 w-5 text-status-info-icon" />
83
- </div>
84
- </div>
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
- <div className="flex-1 min-w-0">
87
- <div className="flex items-start justify-between gap-2">
88
- <div>
89
- <h4 className={cn('text-sm font-medium', isUnread && 'font-semibold')}>
90
- {notification.title}
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
- <div className="mt-2 flex items-center gap-4 text-xs text-muted-foreground">
107
- {currentTotal && (
108
- <div className="flex items-center gap-1">
109
- <DollarSign className="h-3 w-3" />
110
- <span className="font-medium text-foreground">{currentTotal}</span>
111
- </div>
112
- )}
113
- <div className="flex items-center gap-1">
114
- <User className="h-3 w-3" />
115
- <span>{t('sales.notifications.renderer.assignedToYou', 'Assigned to you')}</span>
116
- </div>
117
- </div>
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
- <div className="mt-3 flex gap-2">
120
- <Button
121
- variant="default"
122
- size="sm"
123
- onClick={(e) => {
124
- e.stopPropagation()
125
- handleView()
126
- }}
127
- disabled={executing || (!viewAction && !notification.linkHref)}
128
- className="gap-1"
129
- >
130
- <ExternalLink className="h-3 w-3" />
131
- {t('sales.notifications.renderer.viewOrder', 'View Order')}
132
- </Button>
133
- <Button
134
- variant="ghost"
135
- size="sm"
136
- onClick={(e) => {
137
- e.stopPropagation()
138
- onDismiss()
139
- }}
140
- >
141
- {t('notifications.actions.dismiss', 'Dismiss')}
142
- </Button>
143
- </div>
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
  }