@tuturuuu/ui 0.30.2 → 0.32.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/CHANGELOG.md +49 -0
- package/biome.json +1 -1
- package/package.json +95 -49
- package/src/components/ui/calendar-app/calendar-client-page.test.tsx +57 -0
- package/src/components/ui/calendar-app/calendar-client-page.tsx +13 -4
- package/src/components/ui/calendar-app/calendar-page-shell.tsx +7 -1
- package/src/components/ui/calendar-app/components/calendar-connections-compact.tsx +47 -39
- package/src/components/ui/calendar-app/components/calendar-connections-settings-content.tsx +14 -0
- package/src/components/ui/calendar-app/components/calendar-connections-unified.tsx +4 -0
- package/src/components/ui/calendar-app/components/calendar-sync-attention-button.tsx +47 -0
- package/src/components/ui/calendar-app/components/calendar-sync-recovery.test.tsx +112 -0
- package/src/components/ui/calendar-app/components/calendar-sync-recovery.tsx +206 -0
- package/src/components/ui/calendar-app/components/calendar-types.ts +1 -1
- package/src/components/ui/calendar-app/components/use-calendar-connections-manager.ts +86 -90
- package/src/components/ui/chat/ai-message-markdown.tsx +17 -2
- package/src/components/ui/custom/language-dropdown-item.tsx +6 -14
- package/src/components/ui/custom/nav-link.tsx +7 -7
- package/src/components/ui/custom/nav.tsx +15 -63
- package/src/components/ui/custom/notification-card.tsx +361 -0
- package/src/components/ui/custom/notification-list.tsx +178 -0
- package/src/components/ui/custom/notification-popover-client.tsx +12 -780
- package/src/components/ui/custom/notification-runtime.tsx +23 -0
- package/src/components/ui/custom/onboarding-settings-panel.tsx +8 -55
- package/src/components/ui/custom/satellite-account-switcher-menu.tsx +212 -0
- package/src/components/ui/custom/satellite-brand.tsx +122 -0
- package/src/components/ui/custom/satellite-content.tsx +148 -0
- package/src/components/ui/custom/satellite-footer-actions.tsx +350 -0
- package/src/components/ui/custom/satellite-language-item.tsx +26 -0
- package/src/components/ui/custom/satellite-navigation.tsx +86 -0
- package/src/components/ui/custom/satellite-notification-popover.tsx +272 -0
- package/src/components/ui/custom/satellite-onboarding-settings-panel.tsx +80 -0
- package/src/components/ui/custom/satellite-settings-dialog-shell.tsx +621 -0
- package/src/components/ui/custom/satellite-shell-utils.ts +163 -0
- package/src/components/ui/custom/satellite-shell.test.tsx +169 -0
- package/src/components/ui/custom/satellite-shell.tsx +50 -0
- package/src/components/ui/custom/satellite-theme-dropdown-items.tsx +92 -0
- package/src/components/ui/custom/satellite-user-menu-items.tsx +190 -0
- package/src/components/ui/custom/satellite-user-menu.tsx +93 -0
- package/src/components/ui/custom/satellite-workspace-section.tsx +46 -0
- package/src/components/ui/custom/settings/keyboard-shortcuts-settings.tsx +16 -0
- package/src/components/ui/custom/settings-dialog-shell.tsx +21 -600
- package/src/components/ui/custom/sidebar-context.tsx +5 -14
- package/src/components/ui/custom/sidebar-footer-actions.tsx +19 -322
- package/src/components/ui/custom/structure.tsx +14 -0
- package/src/components/ui/custom/system-language-dropdown-item.tsx +7 -14
- package/src/components/ui/custom/theme-dropdown-items.tsx +2 -85
- package/src/components/ui/custom/use-satellite-shell.tsx +165 -0
- package/src/components/ui/legacy/calendar/agenda-view.tsx +139 -47
- package/src/components/ui/legacy/calendar/calendar-content.test.tsx +116 -0
- package/src/components/ui/legacy/calendar/calendar-content.tsx +38 -74
- package/src/components/ui/legacy/calendar/calendar-event-tone.ts +20 -0
- package/src/components/ui/legacy/calendar/calendar-meeting-link.test.ts +27 -0
- package/src/components/ui/legacy/calendar/calendar-meeting-link.ts +34 -0
- package/src/components/ui/legacy/calendar/calendar-period.ts +28 -0
- package/src/components/ui/legacy/calendar/calendar-shortcuts.test.tsx +107 -0
- package/src/components/ui/legacy/calendar/calendar-views.test.tsx +169 -0
- package/src/components/ui/legacy/calendar/event-modal-header.tsx +52 -0
- package/src/components/ui/legacy/calendar/event-modal.tsx +107 -156
- package/src/components/ui/legacy/calendar/month-calendar.tsx +242 -933
- package/src/components/ui/legacy/calendar/save-calendar-event-drafts.test.ts +25 -0
- package/src/components/ui/legacy/calendar/save-calendar-event-drafts.ts +32 -0
- package/src/components/ui/legacy/calendar/smart-calendar.tsx +3 -0
- package/src/components/ui/legacy/calendar/use-calendar-view-shortcuts.ts +54 -0
- package/src/components/ui/legacy/calendar/use-event-draft-session.test.tsx +59 -0
- package/src/components/ui/legacy/calendar/use-event-draft-session.ts +20 -0
- package/src/components/ui/legacy/calendar/year-calendar.tsx +34 -16
- package/src/components/ui/pwa-status.test.tsx +53 -0
- package/src/components/ui/pwa-status.tsx +113 -0
- package/src/components/ui/report-problem-dialog-content.tsx +350 -0
- package/src/components/ui/report-problem-dialog.tsx +6 -975
- package/src/components/ui/report-problem-model.ts +133 -0
- package/src/components/ui/report-problem-mutation.ts +122 -0
- package/src/components/ui/save-notification.test.tsx +36 -0
- package/src/components/ui/save-notification.tsx +17 -0
- package/src/components/ui/use-report-problem.ts +488 -0
- package/src/declarations.d.ts +2 -0
- package/src/hooks/__tests__/use-calendar-readonly.test.tsx +46 -4
- package/src/hooks/__tests__/use-calendar-sync.test.tsx +24 -0
- package/src/hooks/calendar-date-utils.ts +11 -0
- package/src/hooks/calendar-event-lookup.test.ts +77 -0
- package/src/hooks/calendar-event-lookup.ts +47 -0
- package/src/hooks/calendar-range-cache.ts +52 -0
- package/src/hooks/pwa-install-prompt.ts +44 -0
- package/src/hooks/use-calendar-sync.tsx +23 -100
- package/src/hooks/use-calendar.tsx +21 -77
- package/src/hooks/use-notifications.ts +9 -24
- package/src/hooks/use-open-initial-calendar-event.ts +27 -0
- package/src/hooks/use-settings-dialog-shortcut.test.tsx +41 -0
- package/src/hooks/use-settings-dialog-shortcut.ts +12 -14
- package/src/hooks/use-workspace-presence.ts +0 -18
- package/src/lib/tasks-app-url.test.ts +25 -0
- package/src/lib/tasks-app-url.ts +8 -0
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
AlertCircle,
|
|
5
|
+
AlertTriangle,
|
|
6
|
+
CheckCircle,
|
|
7
|
+
MessageSquareWarning,
|
|
8
|
+
Upload,
|
|
9
|
+
X,
|
|
10
|
+
} from '@tuturuuu/icons';
|
|
11
|
+
import { Button } from '@tuturuuu/ui/button';
|
|
12
|
+
import {
|
|
13
|
+
Dialog,
|
|
14
|
+
DialogContent,
|
|
15
|
+
DialogDescription,
|
|
16
|
+
DialogHeader,
|
|
17
|
+
DialogTitle,
|
|
18
|
+
DialogTrigger,
|
|
19
|
+
} from '@tuturuuu/ui/dialog';
|
|
20
|
+
import { Input } from '@tuturuuu/ui/input';
|
|
21
|
+
import { Label } from '@tuturuuu/ui/label';
|
|
22
|
+
import {
|
|
23
|
+
Select,
|
|
24
|
+
SelectContent,
|
|
25
|
+
SelectItem,
|
|
26
|
+
SelectTrigger,
|
|
27
|
+
SelectValue,
|
|
28
|
+
} from '@tuturuuu/ui/select';
|
|
29
|
+
import { Textarea } from '@tuturuuu/ui/textarea';
|
|
30
|
+
import { cn, isValidBlobUrl } from '@tuturuuu/utils/format';
|
|
31
|
+
import {
|
|
32
|
+
ALLOWED_VIDEO_TYPES,
|
|
33
|
+
DEFAULT_PRODUCTS,
|
|
34
|
+
DEFAULT_SUPPORT_TYPES,
|
|
35
|
+
MAX_FILES,
|
|
36
|
+
type ReportProblemDialogProps,
|
|
37
|
+
} from './report-problem-model';
|
|
38
|
+
import { useReportProblem } from './use-report-problem';
|
|
39
|
+
export function ReportProblemDialogContent({
|
|
40
|
+
ImageComponent,
|
|
41
|
+
products = DEFAULT_PRODUCTS,
|
|
42
|
+
className,
|
|
43
|
+
trigger,
|
|
44
|
+
showTrigger = true,
|
|
45
|
+
...props
|
|
46
|
+
}: ReportProblemDialogProps) {
|
|
47
|
+
const { t } = props;
|
|
48
|
+
const PreviewImage = ImageComponent ?? 'img';
|
|
49
|
+
const {
|
|
50
|
+
dialogOpen,
|
|
51
|
+
handleOpenChange,
|
|
52
|
+
handleSubmit,
|
|
53
|
+
formData,
|
|
54
|
+
validationErrors,
|
|
55
|
+
isSubmitting,
|
|
56
|
+
isCompressing,
|
|
57
|
+
suggestionId,
|
|
58
|
+
mediaUploadId,
|
|
59
|
+
isDragOver,
|
|
60
|
+
fileInputRef,
|
|
61
|
+
handleDragOver,
|
|
62
|
+
handleDragLeave,
|
|
63
|
+
handleDrop,
|
|
64
|
+
handleProductChange,
|
|
65
|
+
handleTypeChange,
|
|
66
|
+
handleSuggestionChange,
|
|
67
|
+
handleMediaUpload,
|
|
68
|
+
mediaPreviews,
|
|
69
|
+
removeMedia,
|
|
70
|
+
} = useReportProblem(props);
|
|
71
|
+
return (
|
|
72
|
+
<Dialog open={dialogOpen} onOpenChange={handleOpenChange}>
|
|
73
|
+
{showTrigger && (
|
|
74
|
+
<DialogTrigger asChild>
|
|
75
|
+
{trigger || (
|
|
76
|
+
<Button variant="secondary" size="sm" className={cn(className)}>
|
|
77
|
+
<MessageSquareWarning className="mr-2 h-4 w-4" />
|
|
78
|
+
{t('report-problem')}
|
|
79
|
+
</Button>
|
|
80
|
+
)}
|
|
81
|
+
</DialogTrigger>
|
|
82
|
+
)}
|
|
83
|
+
<DialogContent className="mx-auto flex max-h-[90vh] w-[calc(100vw-1.5rem)] max-w-7xl flex-col overflow-hidden">
|
|
84
|
+
<DialogHeader className="border-b pb-4">
|
|
85
|
+
<DialogTitle className="flex items-center gap-2 text-lg sm:text-xl">
|
|
86
|
+
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-orange-100 dark:bg-orange-900">
|
|
87
|
+
<AlertTriangle className="h-4 w-4 text-orange-600 dark:text-orange-400" />
|
|
88
|
+
</div>
|
|
89
|
+
{t('report-problem')}
|
|
90
|
+
</DialogTitle>
|
|
91
|
+
<DialogDescription className="mt-2 text-muted-foreground text-sm">
|
|
92
|
+
{t('report-problem-description')}
|
|
93
|
+
</DialogDescription>
|
|
94
|
+
</DialogHeader>
|
|
95
|
+
|
|
96
|
+
<div className="flex-1 overflow-y-auto">
|
|
97
|
+
<form onSubmit={handleSubmit} className="space-y-6">
|
|
98
|
+
<div className="space-y-3">
|
|
99
|
+
<Label
|
|
100
|
+
htmlFor="product"
|
|
101
|
+
className="flex items-center gap-1 font-medium text-sm"
|
|
102
|
+
>
|
|
103
|
+
{t('affected-product-required')}
|
|
104
|
+
</Label>
|
|
105
|
+
<Select
|
|
106
|
+
value={formData.product}
|
|
107
|
+
onValueChange={handleProductChange}
|
|
108
|
+
>
|
|
109
|
+
<SelectTrigger
|
|
110
|
+
className={cn(
|
|
111
|
+
'h-11',
|
|
112
|
+
validationErrors.product &&
|
|
113
|
+
'border-red-500 focus:border-red-500'
|
|
114
|
+
)}
|
|
115
|
+
>
|
|
116
|
+
<SelectValue placeholder={t('select-product-placeholder')} />
|
|
117
|
+
</SelectTrigger>
|
|
118
|
+
<SelectContent>
|
|
119
|
+
{products.map((product) => (
|
|
120
|
+
<SelectItem key={product.value} value={product.value}>
|
|
121
|
+
{product.label}
|
|
122
|
+
</SelectItem>
|
|
123
|
+
))}
|
|
124
|
+
</SelectContent>
|
|
125
|
+
</Select>
|
|
126
|
+
{validationErrors.product && (
|
|
127
|
+
<div className="flex items-center gap-1 text-red-600 text-sm">
|
|
128
|
+
<AlertCircle className="h-3 w-3" />
|
|
129
|
+
{validationErrors.product}
|
|
130
|
+
</div>
|
|
131
|
+
)}
|
|
132
|
+
</div>
|
|
133
|
+
|
|
134
|
+
<div className="space-y-3">
|
|
135
|
+
<Label
|
|
136
|
+
htmlFor="type"
|
|
137
|
+
className="flex items-center gap-1 font-medium text-sm"
|
|
138
|
+
>
|
|
139
|
+
Support Type *
|
|
140
|
+
</Label>
|
|
141
|
+
<Select value={formData.type} onValueChange={handleTypeChange}>
|
|
142
|
+
<SelectTrigger
|
|
143
|
+
className={cn(
|
|
144
|
+
'h-11',
|
|
145
|
+
validationErrors.type &&
|
|
146
|
+
'border-red-500 focus:border-red-500'
|
|
147
|
+
)}
|
|
148
|
+
>
|
|
149
|
+
<SelectValue placeholder="Select support type..." />
|
|
150
|
+
</SelectTrigger>
|
|
151
|
+
<SelectContent>
|
|
152
|
+
{DEFAULT_SUPPORT_TYPES.map((type) => (
|
|
153
|
+
<SelectItem key={type.value} value={type.value}>
|
|
154
|
+
{type.label}
|
|
155
|
+
</SelectItem>
|
|
156
|
+
))}
|
|
157
|
+
</SelectContent>
|
|
158
|
+
</Select>
|
|
159
|
+
{validationErrors.type && (
|
|
160
|
+
<div className="flex items-center gap-1 text-red-600 text-sm">
|
|
161
|
+
<AlertCircle className="h-3 w-3" />
|
|
162
|
+
{validationErrors.type}
|
|
163
|
+
</div>
|
|
164
|
+
)}
|
|
165
|
+
</div>
|
|
166
|
+
|
|
167
|
+
<div className="space-y-3">
|
|
168
|
+
<Label
|
|
169
|
+
htmlFor="suggestion"
|
|
170
|
+
className="flex items-center gap-1 font-medium text-sm"
|
|
171
|
+
>
|
|
172
|
+
{t('suggestion-improve')}
|
|
173
|
+
</Label>
|
|
174
|
+
<Textarea
|
|
175
|
+
id={suggestionId}
|
|
176
|
+
placeholder={t('suggestion-placeholder')}
|
|
177
|
+
value={formData.suggestion}
|
|
178
|
+
onChange={handleSuggestionChange}
|
|
179
|
+
className={cn(
|
|
180
|
+
'max-h-62.5 min-h-30 resize-y',
|
|
181
|
+
validationErrors.suggestion &&
|
|
182
|
+
'border-red-500 focus:border-red-500'
|
|
183
|
+
)}
|
|
184
|
+
/>
|
|
185
|
+
{validationErrors.suggestion && (
|
|
186
|
+
<div className="flex items-center gap-1 text-red-600 text-sm">
|
|
187
|
+
<AlertCircle className="h-3 w-3" />
|
|
188
|
+
{validationErrors.suggestion}
|
|
189
|
+
</div>
|
|
190
|
+
)}
|
|
191
|
+
<div className="text-muted-foreground text-xs">
|
|
192
|
+
{formData.suggestion.length}/1000 characters
|
|
193
|
+
</div>
|
|
194
|
+
</div>
|
|
195
|
+
|
|
196
|
+
<div className="space-y-4">
|
|
197
|
+
<Label className="font-medium text-sm">
|
|
198
|
+
{t('media-optional')} ({formData.media.length}/{MAX_FILES})
|
|
199
|
+
</Label>
|
|
200
|
+
|
|
201
|
+
{formData.media.length < MAX_FILES && (
|
|
202
|
+
<button
|
|
203
|
+
type="button"
|
|
204
|
+
className={cn(
|
|
205
|
+
'relative mt-2 w-full rounded-lg border-2 border-dashed transition-all duration-200',
|
|
206
|
+
isDragOver
|
|
207
|
+
? 'border-orange-400 bg-orange-50 dark:bg-orange-950/20'
|
|
208
|
+
: 'border-gray-300 hover:border-gray-400 dark:border-gray-600 dark:hover:border-gray-500',
|
|
209
|
+
isCompressing && 'pointer-events-none opacity-50'
|
|
210
|
+
)}
|
|
211
|
+
onDragOver={handleDragOver}
|
|
212
|
+
onDragLeave={handleDragLeave}
|
|
213
|
+
onDrop={handleDrop}
|
|
214
|
+
aria-label="Click to upload or drag and drop media files"
|
|
215
|
+
disabled={isCompressing}
|
|
216
|
+
>
|
|
217
|
+
<Input
|
|
218
|
+
ref={fileInputRef}
|
|
219
|
+
type="file"
|
|
220
|
+
accept="image/png,image/jpeg,image/webp,image/gif,video/mp4,video/webm,video/quicktime"
|
|
221
|
+
multiple
|
|
222
|
+
onChange={handleMediaUpload}
|
|
223
|
+
disabled={isSubmitting || isCompressing}
|
|
224
|
+
className="absolute inset-0 h-full w-full cursor-pointer opacity-0"
|
|
225
|
+
id={mediaUploadId}
|
|
226
|
+
/>
|
|
227
|
+
<div className="flex flex-col items-center justify-center px-4 py-8 text-center">
|
|
228
|
+
<div
|
|
229
|
+
className={cn(
|
|
230
|
+
'mb-3 flex h-12 w-12 items-center justify-center rounded-full transition-colors',
|
|
231
|
+
isDragOver
|
|
232
|
+
? 'bg-orange-100 dark:bg-orange-900'
|
|
233
|
+
: 'bg-gray-100 dark:bg-gray-800'
|
|
234
|
+
)}
|
|
235
|
+
>
|
|
236
|
+
<Upload
|
|
237
|
+
className={cn(
|
|
238
|
+
'h-5 w-5',
|
|
239
|
+
isDragOver ? 'text-orange-600' : 'text-gray-400'
|
|
240
|
+
)}
|
|
241
|
+
/>
|
|
242
|
+
</div>
|
|
243
|
+
<p className="mb-1 font-medium text-sm">
|
|
244
|
+
{isCompressing
|
|
245
|
+
? 'Compressing...'
|
|
246
|
+
: isDragOver
|
|
247
|
+
? 'Drop files here'
|
|
248
|
+
: 'Click to upload or drag and drop'}
|
|
249
|
+
</p>
|
|
250
|
+
<p className="text-muted-foreground text-xs">
|
|
251
|
+
Images (PNG, JPG, GIF, WebP) or Videos (MP4, WebM, MOV) up
|
|
252
|
+
to 5MB each
|
|
253
|
+
</p>
|
|
254
|
+
</div>
|
|
255
|
+
</button>
|
|
256
|
+
)}
|
|
257
|
+
|
|
258
|
+
{validationErrors.media && (
|
|
259
|
+
<div className="text-red-600 text-sm">
|
|
260
|
+
{validationErrors.media}
|
|
261
|
+
</div>
|
|
262
|
+
)}
|
|
263
|
+
|
|
264
|
+
{mediaPreviews.length > 0 && (
|
|
265
|
+
<div className="grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-4">
|
|
266
|
+
{mediaPreviews.map((preview, index) => {
|
|
267
|
+
const file = formData.media[index];
|
|
268
|
+
const isVideo =
|
|
269
|
+
file && ALLOWED_VIDEO_TYPES.includes(file.type);
|
|
270
|
+
|
|
271
|
+
return (
|
|
272
|
+
<div key={preview} className="group relative">
|
|
273
|
+
<div className="aspect-square overflow-hidden rounded-lg border-2 border-gray-200 bg-gray-50 dark:border-gray-700 dark:bg-gray-800">
|
|
274
|
+
{isVideo ? (
|
|
275
|
+
<video
|
|
276
|
+
src={isValidBlobUrl(preview) ? preview : ''}
|
|
277
|
+
className="h-full w-full object-cover"
|
|
278
|
+
controls={false}
|
|
279
|
+
muted
|
|
280
|
+
playsInline
|
|
281
|
+
/>
|
|
282
|
+
) : (
|
|
283
|
+
<PreviewImage
|
|
284
|
+
src={
|
|
285
|
+
isValidBlobUrl(preview)
|
|
286
|
+
? preview
|
|
287
|
+
: '/placeholder.svg'
|
|
288
|
+
}
|
|
289
|
+
alt={t('media-alt', { number: index + 1 })}
|
|
290
|
+
className="h-full w-full object-cover"
|
|
291
|
+
width={100}
|
|
292
|
+
height={100}
|
|
293
|
+
/>
|
|
294
|
+
)}
|
|
295
|
+
</div>
|
|
296
|
+
<Button
|
|
297
|
+
type="button"
|
|
298
|
+
variant="destructive"
|
|
299
|
+
size="icon"
|
|
300
|
+
className="absolute -top-2 -right-2 h-6 w-6 rounded-full opacity-0 shadow-lg transition-opacity group-hover:opacity-100"
|
|
301
|
+
onClick={() => removeMedia(index)}
|
|
302
|
+
>
|
|
303
|
+
<X className="h-3 w-3" />
|
|
304
|
+
</Button>
|
|
305
|
+
</div>
|
|
306
|
+
);
|
|
307
|
+
})}
|
|
308
|
+
</div>
|
|
309
|
+
)}
|
|
310
|
+
</div>
|
|
311
|
+
|
|
312
|
+
<div className="flex w-full flex-col-reverse gap-3 border-t pt-4 sm:flex-row sm:justify-end">
|
|
313
|
+
<Button
|
|
314
|
+
type="button"
|
|
315
|
+
variant="outline"
|
|
316
|
+
onClick={() => handleOpenChange(false)}
|
|
317
|
+
disabled={isSubmitting}
|
|
318
|
+
className="w-full sm:w-auto"
|
|
319
|
+
>
|
|
320
|
+
{t('cancel')}
|
|
321
|
+
</Button>
|
|
322
|
+
<Button
|
|
323
|
+
type="submit"
|
|
324
|
+
disabled={
|
|
325
|
+
!formData.product ||
|
|
326
|
+
!formData.type ||
|
|
327
|
+
!formData.suggestion.trim() ||
|
|
328
|
+
isSubmitting
|
|
329
|
+
}
|
|
330
|
+
className="w-full bg-orange-600 hover:bg-orange-700 disabled:opacity-50 sm:w-auto"
|
|
331
|
+
>
|
|
332
|
+
{isSubmitting ? (
|
|
333
|
+
<div className="flex items-center gap-2">
|
|
334
|
+
<div className="h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent" />
|
|
335
|
+
{t('submitting')}
|
|
336
|
+
</div>
|
|
337
|
+
) : (
|
|
338
|
+
<div className="flex items-center gap-2">
|
|
339
|
+
<CheckCircle className="h-4 w-4" />
|
|
340
|
+
{t('submit-report')}
|
|
341
|
+
</div>
|
|
342
|
+
)}
|
|
343
|
+
</Button>
|
|
344
|
+
</div>
|
|
345
|
+
</form>
|
|
346
|
+
</div>
|
|
347
|
+
</DialogContent>
|
|
348
|
+
</Dialog>
|
|
349
|
+
);
|
|
350
|
+
}
|