Spaces:
Sleeping
Sleeping
Download src/components/PasswordGate.tsx from brestok/supplier-segmentation: direct link, hf CLI and curl.
- Browser
- Download file 2.12 kB
-
https://huggingface.co/spaces/brestok/supplier-segmentation/resolve/main/src/components/PasswordGate.tsx
- Command line
-
hf download hf://spaces/brestok/supplier-segmentation/src/components/PasswordGate.tsx
-
curl -L -o PasswordGate.tsx https://huggingface.co/spaces/brestok/supplier-segmentation/resolve/main/src/components/PasswordGate.tsx
2.12 kB
| import React, { useState } from 'react'; | |
| import { Field, TextInput } from './controls'; | |
| /** | |
| * Temporary front-end lock until the backend has real auth. The password ships | |
| * in the bundle, so this only keeps casual visitors out — it protects nothing. | |
| */ | |
| const PASSWORD = process.env.REACT_APP_ACCESS_PASSWORD || 'Taric-Kiwi-7428'; | |
| const STORAGE_KEY = 'cargoflow.unlocked'; | |
| function readUnlocked(): boolean { | |
| try { | |
| return localStorage.getItem(STORAGE_KEY) === PASSWORD; | |
| } catch { | |
| return false; | |
| } | |
| } | |
| export function PasswordGate({ children }: { children: React.ReactNode }) { | |
| const [unlocked, setUnlocked] = useState(readUnlocked); | |
| const [value, setValue] = useState(''); | |
| const [wrong, setWrong] = useState(false); | |
| if (unlocked) return <>{children}</>; | |
| const onSubmit = (event: React.FormEvent) => { | |
| event.preventDefault(); | |
| if (value !== PASSWORD) { | |
| setWrong(true); | |
| return; | |
| } | |
| try { | |
| localStorage.setItem(STORAGE_KEY, PASSWORD); | |
| } catch { | |
| // Private mode: stay unlocked for this tab only. | |
| } | |
| setUnlocked(true); | |
| }; | |
| return ( | |
| <main className="mx-auto my-[52px] max-w-[420px] px-[22px] max-[560px]:my-[30px] max-[560px]:px-4"> | |
| <div className="mb-6 text-center text-2xl font-[750] tracking-[-1px]"> | |
| Cargo<span className="text-brand-accent">Flow</span> | |
| </div> | |
| <form className="cf-card" onSubmit={onSubmit}> | |
| <Field label="Password" htmlFor="access-password"> | |
| <TextInput | |
| id="access-password" | |
| type="password" | |
| autoFocus | |
| autoComplete="current-password" | |
| value={value} | |
| aria-invalid={wrong} | |
| className={wrong ? 'border-danger' : ''} | |
| onChange={(event) => { | |
| setValue(event.target.value); | |
| setWrong(false); | |
| }} | |
| /> | |
| {wrong ? <p className="mt-2 text-xs text-danger">Wrong password.</p> : null} | |
| </Field> | |
| <button type="submit" className="cf-primary" disabled={value === ''}> | |
| Enter | |
| </button> | |
| </form> | |
| </main> | |
| ); | |
| } | |