@dilipod/ui 0.4.2 → 0.4.3

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,7 +1,7 @@
1
1
  'use client'
2
2
 
3
3
  import * as React from 'react'
4
- import { Plus, PencilSimple, Trash, Warning, CheckCircle, Question, Lightning } from '@phosphor-icons/react'
4
+ import { Plus, PencilSimple, Trash, Warning, CheckCircle, Question, Lightning, Check } from '@phosphor-icons/react'
5
5
  import { cn } from '../lib/utils'
6
6
  import { Button } from './button'
7
7
  import { Badge } from './badge'
@@ -37,12 +37,15 @@ export interface ScenariosManagerProps {
37
37
  onAdd: (scenario: Omit<Scenario, 'id'>) => Promise<void>
38
38
  onUpdate: (id: string, scenario: Omit<Scenario, 'id'>) => Promise<void>
39
39
  onDelete: (id: string) => Promise<void>
40
+ onComplete?: () => Promise<void>
40
41
  suggestions?: ScenarioSuggestion[]
41
42
  isLoading?: boolean
43
+ isComplete?: boolean
44
+ minScenariosToComplete?: number
42
45
  className?: string
43
46
  }
44
47
 
45
- // Type configuration
48
+ // Type configuration - using Dilipod brand colors
46
49
  const typeConfig: Record<ScenarioType, {
47
50
  label: string
48
51
  icon: React.ElementType
@@ -60,8 +63,8 @@ const typeConfig: Record<ScenarioType, {
60
63
  default_behavior: {
61
64
  label: 'Handle it',
62
65
  icon: CheckCircle,
63
- color: 'text-blue-600',
64
- bgColor: 'bg-blue-50',
66
+ color: 'text-[var(--cyan)]',
67
+ bgColor: 'bg-[var(--cyan)]/10',
65
68
  description: 'Proceed automatically using this rule',
66
69
  },
67
70
  quality_check: {
@@ -74,8 +77,8 @@ const typeConfig: Record<ScenarioType, {
74
77
  edge_case: {
75
78
  label: 'Watch out',
76
79
  icon: Question,
77
- color: 'text-purple-600',
78
- bgColor: 'bg-purple-50',
80
+ color: 'text-muted-foreground',
81
+ bgColor: 'bg-muted',
79
82
  description: 'Common mistakes or tricky situations',
80
83
  },
81
84
  }
@@ -94,21 +97,21 @@ function ScenarioCard({
94
97
  const Icon = config.icon
95
98
 
96
99
  return (
97
- <div className="group relative border border-gray-200 rounded-sm p-4 hover:border-gray-300 transition-colors">
100
+ <div className="group relative border border-border rounded-sm p-4 hover:border-[var(--cyan)]/30 hover:bg-[var(--cyan)]/[0.02] transition-all">
98
101
  <div className="flex items-start justify-between gap-3">
99
102
  <div className="flex items-start gap-3 flex-1 min-w-0">
100
- <div className={cn('w-8 h-8 rounded-sm flex items-center justify-center shrink-0', config.bgColor)}>
101
- <Icon size={16} weight="fill" className={config.color} />
103
+ <div className={cn('w-9 h-9 rounded-sm flex items-center justify-center shrink-0', config.bgColor)}>
104
+ <Icon size={18} weight="fill" className={config.color} />
102
105
  </div>
103
106
  <div className="flex-1 min-w-0">
104
- <div className="flex items-center gap-2 mb-1">
105
- <Badge variant="outline" size="sm">{config.label}</Badge>
107
+ <div className="flex items-center gap-2 mb-1.5">
108
+ <Badge variant="outline" size="sm" className="font-medium">{config.label}</Badge>
106
109
  </div>
107
- <p className="text-sm text-[var(--black)] font-medium">
108
- When: <span className="font-normal">{scenario.situation}</span>
110
+ <p className="text-sm text-[var(--black)]">
111
+ <span className="font-medium">When:</span> {scenario.situation}
109
112
  </p>
110
113
  <p className="text-sm text-muted-foreground mt-1">
111
- Action: <span className="text-[var(--black)]">{scenario.action}</span>
114
+ <span className="text-[var(--black)] font-medium">Action:</span> {scenario.action}
112
115
  </p>
113
116
  </div>
114
117
  </div>
@@ -116,7 +119,7 @@ function ScenarioCard({
116
119
  <Button
117
120
  variant="ghost"
118
121
  size="icon"
119
- className="h-8 w-8"
122
+ className="h-8 w-8 text-muted-foreground hover:text-[var(--black)]"
120
123
  onClick={onEdit}
121
124
  >
122
125
  <PencilSimple size={16} />
@@ -124,7 +127,7 @@ function ScenarioCard({
124
127
  <Button
125
128
  variant="ghost"
126
129
  size="icon"
127
- className="h-8 w-8 text-red-600 hover:text-red-700 hover:bg-red-50"
130
+ className="h-8 w-8 text-muted-foreground hover:text-red-600 hover:bg-red-50"
128
131
  onClick={onDelete}
129
132
  >
130
133
  <Trash size={16} />
@@ -145,21 +148,18 @@ function SuggestionChip({
145
148
  onAdd: () => void
146
149
  disabled?: boolean
147
150
  }) {
148
- const config = typeConfig[suggestion.type]
149
- const Icon = config.icon
150
-
151
151
  return (
152
152
  <button
153
153
  type="button"
154
154
  onClick={onAdd}
155
155
  disabled={disabled}
156
156
  className={cn(
157
- 'inline-flex items-center gap-2 px-3 py-2 rounded-sm border border-dashed border-gray-300',
157
+ 'inline-flex items-center gap-1.5 px-3 py-1.5 rounded-sm border border-dashed border-border',
158
158
  'text-sm text-muted-foreground hover:border-[var(--cyan)] hover:text-[var(--cyan)] hover:bg-[var(--cyan)]/5',
159
- 'transition-colors disabled:opacity-50 disabled:cursor-not-allowed'
159
+ 'transition-all disabled:opacity-50 disabled:cursor-not-allowed'
160
160
  )}
161
161
  >
162
- <Plus size={14} />
162
+ <Plus size={14} weight="bold" />
163
163
  {suggestion.situation}
164
164
  </button>
165
165
  )
@@ -276,13 +276,19 @@ export function ScenariosManager({
276
276
  onAdd,
277
277
  onUpdate,
278
278
  onDelete,
279
+ onComplete,
279
280
  suggestions = [],
280
281
  isLoading,
282
+ isComplete = false,
283
+ minScenariosToComplete = 1,
281
284
  className,
282
285
  }: ScenariosManagerProps) {
283
286
  const [dialogOpen, setDialogOpen] = React.useState(false)
284
287
  const [editingScenario, setEditingScenario] = React.useState<Scenario | null>(null)
285
288
  const [deletingId, setDeletingId] = React.useState<string | null>(null)
289
+ const [isCompleting, setIsCompleting] = React.useState(false)
290
+
291
+ const canComplete = scenarios.length >= minScenariosToComplete && !isComplete && onComplete
286
292
 
287
293
  const handleAddClick = () => {
288
294
  setEditingScenario(null)
@@ -315,6 +321,16 @@ export function ScenariosManager({
315
321
  await onAdd(suggestion)
316
322
  }
317
323
 
324
+ const handleComplete = async () => {
325
+ if (!onComplete) return
326
+ setIsCompleting(true)
327
+ try {
328
+ await onComplete()
329
+ } finally {
330
+ setIsCompleting(false)
331
+ }
332
+ }
333
+
318
334
  // Filter out suggestions that already exist
319
335
  const filteredSuggestions = suggestions.filter(
320
336
  (s) => !scenarios.some(
@@ -361,20 +377,22 @@ export function ScenariosManager({
361
377
 
362
378
  {/* Empty state */}
363
379
  {scenarios.length === 0 && (
364
- <div className="border border-dashed border-gray-300 rounded-sm p-8 text-center">
365
- <Lightning size={32} className="text-gray-300 mx-auto mb-3" />
380
+ <div className="border border-dashed border-border rounded-sm p-8 text-center">
381
+ <div className="w-12 h-12 rounded-sm bg-muted flex items-center justify-center mx-auto mb-3">
382
+ <Lightning size={24} className="text-muted-foreground" />
383
+ </div>
366
384
  <p className="text-sm text-muted-foreground mb-4">
367
385
  No scenarios yet. Add rules for how the worker should handle edge cases.
368
386
  </p>
369
387
  <Button variant="outline" size="sm" onClick={handleAddClick}>
370
- <Plus size={16} className="mr-1" />
388
+ <Plus size={16} className="mr-1.5" />
371
389
  Add your first scenario
372
390
  </Button>
373
391
  </div>
374
392
  )}
375
393
 
376
394
  {/* Suggestions */}
377
- {filteredSuggestions.length > 0 && (
395
+ {filteredSuggestions.length > 0 && !isComplete && (
378
396
  <div className="pt-2">
379
397
  <p className="text-xs text-muted-foreground mb-2">Suggested scenarios:</p>
380
398
  <div className="flex flex-wrap gap-2">
@@ -390,6 +408,45 @@ export function ScenariosManager({
390
408
  </div>
391
409
  )}
392
410
 
411
+ {/* Complete button */}
412
+ {canComplete && (
413
+ <div className="pt-4 border-t border-border">
414
+ <div className="flex items-center justify-between gap-4 bg-[var(--cyan)]/5 rounded-sm p-4 -mx-1">
415
+ <div>
416
+ <p className="text-sm font-medium text-[var(--black)]">
417
+ Ready to proceed?
418
+ </p>
419
+ <p className="text-xs text-muted-foreground mt-0.5">
420
+ Mark your scenarios as complete to continue with the onboarding.
421
+ </p>
422
+ </div>
423
+ <Button
424
+ onClick={handleComplete}
425
+ disabled={isCompleting}
426
+ loading={isCompleting}
427
+ size="sm"
428
+ className="shrink-0"
429
+ >
430
+ <Check size={16} className="mr-1.5" />
431
+ Mark complete
432
+ </Button>
433
+ </div>
434
+ </div>
435
+ )}
436
+
437
+ {/* Complete state */}
438
+ {isComplete && (
439
+ <div className="pt-4 border-t border-border">
440
+ <div className="flex items-center gap-2 text-[var(--cyan)]">
441
+ <CheckCircle size={16} weight="fill" />
442
+ <p className="text-sm font-medium">Scenarios completed</p>
443
+ </div>
444
+ <p className="text-xs text-muted-foreground mt-1">
445
+ You can still add or edit scenarios while we build your worker.
446
+ </p>
447
+ </div>
448
+ )}
449
+
393
450
  {/* Dialog */}
394
451
  <ScenarioDialog
395
452
  open={dialogOpen}