136 lines
5.2 KiB
JavaScript
136 lines
5.2 KiB
JavaScript
import { useState } from 'react'
|
||
import { PHASE2_FEATURE_DEFS, isFeatureEnabled, setFeatureEnabled, usePhase2Features } from '../../../hooks/usePhase2Features'
|
||
|
||
const SECRET = '4034'
|
||
|
||
function PinGate({ onUnlock }) {
|
||
const [pin, setPin] = useState('')
|
||
const [error, setError] = useState(false)
|
||
|
||
function submit() {
|
||
if (pin === SECRET) {
|
||
onUnlock()
|
||
} else {
|
||
setError(true)
|
||
setPin('')
|
||
setTimeout(() => setError(false), 1500)
|
||
}
|
||
}
|
||
|
||
return (
|
||
<div className="flex flex-col items-center justify-center gap-5 py-16 max-w-xs mx-auto">
|
||
<div className="flex h-12 w-12 items-center justify-center rounded-xl bg-slate-100 text-2xl">🔒</div>
|
||
<div className="text-center">
|
||
<p className="font-semibold text-slate-800">Περιορισμένη πρόσβαση</p>
|
||
<p className="text-sm text-slate-400 mt-1">Εισάγετε τον κωδικό για να συνεχίσετε</p>
|
||
</div>
|
||
<div className="flex flex-col items-center gap-3 w-full">
|
||
<input
|
||
type="password"
|
||
value={pin}
|
||
onChange={e => setPin(e.target.value)}
|
||
onKeyDown={e => e.key === 'Enter' && submit()}
|
||
autoFocus
|
||
maxLength={8}
|
||
placeholder="••••"
|
||
className={`w-full text-center text-xl tracking-[0.4em] border rounded-xl px-4 py-3 outline-none transition-colors ${
|
||
error ? 'border-red-400 bg-red-50 text-red-600' : 'border-slate-200 focus:border-sky-400'
|
||
}`}
|
||
/>
|
||
{error && <p className="text-xs text-red-500 font-medium">Λάθος κωδικός</p>}
|
||
<button
|
||
onClick={submit}
|
||
className="w-full rounded-xl bg-slate-900 text-white font-semibold py-2.5 text-sm hover:bg-slate-700 transition-colors"
|
||
>
|
||
Είσοδος
|
||
</button>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
function Toggle({ checked, onChange }) {
|
||
return (
|
||
<button
|
||
role="switch"
|
||
aria-checked={checked}
|
||
onClick={() => onChange(!checked)}
|
||
style={{
|
||
width: 44, height: 24, borderRadius: 999, border: 'none', cursor: 'pointer',
|
||
background: checked ? '#16a34a' : '#d1d5db',
|
||
position: 'relative', transition: 'background 150ms', flexShrink: 0,
|
||
}}
|
||
>
|
||
<span style={{
|
||
position: 'absolute', top: 3, left: checked ? 23 : 3,
|
||
width: 18, height: 18, borderRadius: '50%', background: 'white',
|
||
transition: 'left 150ms', boxShadow: '0 1px 3px rgba(0,0,0,0.2)',
|
||
}} />
|
||
</button>
|
||
)
|
||
}
|
||
|
||
export default function Phase2FeaturesTab() {
|
||
const [unlocked, setUnlocked] = useState(false)
|
||
const features = usePhase2Features()
|
||
|
||
if (!unlocked) return <PinGate onUnlock={() => setUnlocked(true)} />
|
||
|
||
const allOn = features.every(f => f.enabled)
|
||
const allOff = features.every(f => !f.enabled)
|
||
|
||
function toggleAll(value) {
|
||
PHASE2_FEATURE_DEFS.forEach(f => setFeatureEnabled(f.id, value))
|
||
}
|
||
|
||
return (
|
||
<div className="space-y-4 max-w-xl">
|
||
<div className="rounded-lg border border-blue-200 bg-blue-50 px-4 py-3 text-xs text-blue-800">
|
||
Αυτές οι επιλογές ελέγχουν ποιες σελίδες Phase 2 εμφανίζονται στο πλαϊνό μενού.
|
||
Απενεργοποίηση <strong>δεν σβήνει δεδομένα</strong> — απλώς κρύβει τον σύνδεσμο.
|
||
Χρήσιμο για να κρατάτε σελίδες σε εξέλιξη κρυφές από πελάτες.
|
||
</div>
|
||
|
||
<div className="card divide-y divide-gray-100">
|
||
{/* Master toggle row */}
|
||
<div className="flex items-center justify-between gap-4 px-5 py-3 bg-gray-50/60">
|
||
<span className="text-sm font-semibold text-gray-600">Όλες οι λειτουργίες</span>
|
||
<div className="flex gap-3">
|
||
<button
|
||
onClick={() => toggleAll(true)}
|
||
disabled={allOn}
|
||
className="text-xs font-semibold px-3 py-1 rounded-full border border-green-300 text-green-700 hover:bg-green-50 disabled:opacity-40 disabled:cursor-default"
|
||
>
|
||
Ενεργοποίηση όλων
|
||
</button>
|
||
<button
|
||
onClick={() => toggleAll(false)}
|
||
disabled={allOff}
|
||
className="text-xs font-semibold px-3 py-1 rounded-full border border-red-300 text-red-600 hover:bg-red-50 disabled:opacity-40 disabled:cursor-default"
|
||
>
|
||
Απενεργοποίηση όλων
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
{features.map(f => (
|
||
<div key={f.id} className="flex items-center justify-between gap-4 px-5 py-3">
|
||
<div>
|
||
<p className="text-sm font-medium text-gray-700">{f.label}</p>
|
||
<p className="text-xs text-gray-400 mt-0.5 font-mono">{f.route}</p>
|
||
</div>
|
||
<Toggle
|
||
checked={f.enabled}
|
||
onChange={val => setFeatureEnabled(f.id, val)}
|
||
/>
|
||
</div>
|
||
))}
|
||
</div>
|
||
|
||
<p className="text-xs text-gray-400">
|
||
Οι ρυθμίσεις αποθηκεύονται τοπικά στον browser. Ισχύουν αμέσως χωρίς ανανέωση.
|
||
</p>
|
||
</div>
|
||
)
|
||
}
|