File size: 6,470 Bytes
921d377
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/**
 * ConfirmForgetDialog — AWS-style confirmation for destructive memory actions.
 *
 * The user must type the persona name exactly to enable the confirm button.
 * This prevents accidental deletions while keeping the UX lightweight
 * (no password re-entry needed).
 *
 * Used for:
 *  - Forgetting a single memory
 *  - Forgetting ALL memories for a persona
 *
 * Safety: memories are deleted, the persona itself is NEVER deleted.
 */
import React, { useState, useRef, useEffect } from 'react';
import { AlertTriangle, Brain, X } from 'lucide-react';
// ---------------------------------------------------------------------------
// Component
// ---------------------------------------------------------------------------
export default function ConfirmForgetDialog({ mode, personaName, memoryCount = 0, memoryLabel, memoryCategory, onConfirm, onCancel, loading = false, }) {
    const [typed, setTyped] = useState('');
    const inputRef = useRef(null);
    // Auto-focus the input on mount
    useEffect(() => {
        const t = setTimeout(() => inputRef.current?.focus(), 80);
        return () => clearTimeout(t);
    }, []);
    const nameMatches = typed.trim().toLowerCase() === personaName.trim().toLowerCase();
    const canConfirm = nameMatches && !loading;
    const handleKeyDown = (e) => {
        if (e.key === 'Enter' && canConfirm)
            onConfirm();
        if (e.key === 'Escape')
            onCancel();
    };
    return (<div className="fixed inset-0 z-[250] bg-black/60 backdrop-blur-sm flex items-center justify-center p-4" onClick={(e) => { if (e.target === e.currentTarget)
        onCancel(); }}>
      <div className="w-full max-w-md rounded-3xl border border-white/10 bg-[#0b0b0b] shadow-2xl shadow-black/40 overflow-hidden animate-[fadeIn_200ms_ease-out]" onClick={(e) => e.stopPropagation()}>
        {/* Header */}
        <div className="px-6 py-4 border-b border-white/10 flex items-center justify-between">
          <div className="flex items-center gap-3">
            {mode === 'all' ? (<div className="w-9 h-9 rounded-xl bg-red-500/10 border border-red-500/20 flex items-center justify-center">
                <Brain size={18} className="text-red-400"/>
              </div>) : (<div className="w-9 h-9 rounded-xl bg-amber-500/10 border border-amber-500/20 flex items-center justify-center">
                <AlertTriangle size={18} className="text-amber-400"/>
              </div>)}
            <div>
              <div className="text-white/90 font-semibold text-sm">
                {mode === 'all' ? 'Forget All Memories?' : 'Forget This Memory?'}
              </div>
              <div className="text-[11px] text-white/40">
                This action cannot be undone
              </div>
            </div>
          </div>
          <button type="button" onClick={onCancel} className="p-2 rounded-xl hover:bg-white/5 text-white/40 hover:text-white/70 transition-all">
            <X size={16}/>
          </button>
        </div>

        {/* Body */}
        <div className="px-6 py-5 space-y-4">
          {/* What's being deleted */}
          {mode === 'single' && memoryLabel && (<div className="rounded-2xl border border-white/10 bg-white/5 px-4 py-3">
              <div className="text-sm text-white/85 leading-relaxed">
                &ldquo;{memoryLabel}&rdquo;
              </div>
              {memoryCategory && (<div className="text-[11px] text-white/40 mt-1">
                  category: {memoryCategory}
                </div>)}
            </div>)}

          {mode === 'all' && (<div className="rounded-2xl border border-red-500/15 bg-red-500/5 px-4 py-3 space-y-1">
              <div className="text-sm text-red-300/90">
                This will erase{' '}
                <span className="font-semibold text-red-300">
                  {memoryCount === 1 ? '1 memory' : `all ${memoryCount} memories`}
                </span>{' '}
                stored for <span className="font-semibold text-red-300">{personaName}</span>.
              </div>
              <div className="text-[11px] text-white/40">
                The persona itself will NOT be deleted — only memories will be cleared.
              </div>
            </div>)}

          {mode === 'single' && (<div className="text-[12px] text-white/50 leading-relaxed">
              This memory will be permanently removed from{' '}
              <span className="text-white/70 font-medium">{personaName}</span>.
              The persona itself will not be affected.
            </div>)}

          {/* Type-to-confirm input */}
          <div className="space-y-2">
            <label className="text-[12px] text-white/50">
              Type <span className="text-white/80 font-semibold">{personaName}</span> to confirm
            </label>
            <input ref={inputRef} type="text" value={typed} onChange={(e) => setTyped(e.target.value)} onKeyDown={handleKeyDown} placeholder={personaName} className={[
            'w-full px-4 py-3 rounded-2xl border text-sm text-white outline-none transition-all',
            'bg-white/5 placeholder:text-white/15',
            nameMatches
                ? 'border-green-500/30 bg-green-500/5'
                : 'border-white/10 focus:border-white/20',
        ].join(' ')} autoComplete="off" spellCheck={false}/>
          </div>
        </div>

        {/* Footer */}
        <div className="px-6 py-4 border-t border-white/10 flex items-center justify-end gap-3">
          <button type="button" onClick={onCancel} className="px-4 py-2.5 rounded-2xl bg-white/5 hover:bg-white/10 border border-white/10 text-sm text-white/70 transition-all">
            Cancel
          </button>
          <button type="button" onClick={onConfirm} disabled={!canConfirm} className={[
            'px-5 py-2.5 rounded-2xl border text-sm font-semibold transition-all',
            canConfirm
                ? 'bg-red-500/15 hover:bg-red-500/25 border-red-500/25 hover:border-red-500/40 text-red-400 cursor-pointer'
                : 'bg-white/5 border-white/10 text-white/25 cursor-not-allowed',
        ].join(' ')}>
            {loading ? (<span className="flex items-center gap-2">
                <span className="w-3.5 h-3.5 border-2 border-red-400/30 border-t-red-400 rounded-full animate-spin"/>
                Forgetting...
              </span>) : mode === 'all' ? (`Forget All (${memoryCount})`) : ('Forget Memory')}
          </button>
        </div>
      </div>
    </div>);
}