/ src / components / ui / IntentProbe.tsx
IntentProbe.tsx
  1  // Copyright (c) 2026 VPL Solutions. All rights reserved.
  2  // Licensed under the MIT License. See LICENSE for details.
  3  
  4  import { useState } from 'react';
  5  import { ChevronRight, X } from 'lucide-react';
  6  import {
  7    INTENT_OPTIONS,
  8    TOPOLOGY_OPTIONS,
  9    getIntentResponse,
 10    type IntentKey,
 11    type TopologyKey,
 12  } from '../../data/intentResponses';
 13  
 14  interface IntentProbeProps {
 15    onComplete: (intent: IntentKey, topology: TopologyKey) => void;
 16    onSkip: () => void;
 17  }
 18  
 19  export function IntentProbe({ onComplete, onSkip }: IntentProbeProps) {
 20    const [step, setStep] = useState<1 | 2 | 3>(1);
 21    const [intent, setIntent] = useState<IntentKey | null>(null);
 22    const [topology, setTopology] = useState<TopologyKey | null>(null);
 23  
 24    function selectIntent(key: IntentKey) {
 25      setIntent(key);
 26      setStep(2);
 27    }
 28  
 29    function selectTopology(key: TopologyKey) {
 30      setTopology(key);
 31      setStep(3);
 32      if (intent) {
 33        onComplete(intent, key);
 34      }
 35    }
 36  
 37    return (
 38      <div className="bg-white/[0.04] rounded-xl border border-white/10 p-6 backdrop-blur-sm max-w-sm w-full">
 39        {/* Header with skip */}
 40        <div className="flex items-start justify-between mb-4">
 41          <p className="text-xs uppercase tracking-widest text-white/30">
 42            {step === 1 && 'Quick setup'}
 43            {step === 2 && 'One more'}
 44            {step === 3 && 'Got it'}
 45          </p>
 46          <button
 47            onClick={onSkip}
 48            className="text-white/25 hover:text-white/50 transition-colors p-0.5 -mr-1 -mt-1"
 49            aria-label="Skip setup"
 50          >
 51            <X className="w-4 h-4" />
 52          </button>
 53        </div>
 54  
 55        {/* Step 1: Intent */}
 56        {step === 1 && (
 57          <div className="space-y-3">
 58            <p className="text-sm text-white/70 font-medium">
 59              How are you planning to use Meridian?
 60            </p>
 61            <div className="space-y-2">
 62              {INTENT_OPTIONS.map(({ key, label }) => (
 63                <button
 64                  key={key}
 65                  onClick={() => selectIntent(key)}
 66                  className="w-full text-left px-3.5 py-2.5 rounded-lg border border-white/10 text-sm text-white/60 hover:text-white/90 hover:border-violet-500/40 hover:bg-violet-500/10 transition-all flex items-center justify-between group"
 67                >
 68                  {label}
 69                  <ChevronRight className="w-3.5 h-3.5 opacity-0 group-hover:opacity-100 transition-opacity" />
 70                </button>
 71              ))}
 72            </div>
 73          </div>
 74        )}
 75  
 76        {/* Step 2: Topology */}
 77        {step === 2 && (
 78          <div className="space-y-3">
 79            <p className="text-sm text-white/70 font-medium">
 80              Where will this run?
 81            </p>
 82            <div className="flex gap-2">
 83              {TOPOLOGY_OPTIONS.map(({ key, label }) => (
 84                <button
 85                  key={key}
 86                  onClick={() => selectTopology(key)}
 87                  className="flex-1 px-3 py-2.5 rounded-lg border border-white/10 text-sm text-white/60 hover:text-white/90 hover:border-teal-500/40 hover:bg-teal-500/10 transition-all text-center"
 88                >
 89                  {label}
 90                </button>
 91              ))}
 92            </div>
 93          </div>
 94        )}
 95  
 96        {/* Step 3: Response */}
 97        {step === 3 && intent && topology && (
 98          <div className="space-y-3">
 99            <p className="text-sm text-white/60 leading-relaxed">
100              {getIntentResponse(intent, topology)}
101            </p>
102            <div className="flex items-center gap-1.5 text-xs text-white/25">
103              <span className="inline-block w-1 h-1 rounded-full bg-teal-400/50" />
104              Selection saved
105            </div>
106          </div>
107        )}
108  
109        {/* Progress dots */}
110        <div className="flex items-center justify-center gap-1.5 mt-4">
111          {[1, 2, 3].map((s) => (
112            <div
113              key={s}
114              className={`w-1.5 h-1.5 rounded-full transition-colors ${
115                s === step
116                  ? 'bg-violet-400/70'
117                  : s < step
118                    ? 'bg-teal-400/40'
119                    : 'bg-white/10'
120              }`}
121            />
122          ))}
123        </div>
124      </div>
125    );
126  }