From 37d7a076d308f257563a3db995831a45f544cd3f Mon Sep 17 00:00:00 2001 From: Lilith Date: Sun, 22 Feb 2026 12:07:45 -0800 Subject: [PATCH] =?UTF-8?q?chore(pages):=20=F0=9F=94=A7=20standardize=20pa?= =?UTF-8?q?ge=20configs=20across=207=20directories=20with=20consistent=20n?= =?UTF-8?q?aming=20and=20validation=20rules?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- .../src/pages/features/FeaturesPage.css | 82 +++++++++++++------ .../src/pages/features/FeaturesPage.tsx | 30 +++---- .../src/pages/features/featureRegistry.ts | 10 +-- tools/talent-scout/scripts/cli/run | 21 +++-- .../talent-scout/scripts/cli/services-captcha | 6 ++ tools/talent-scout/scripts/cli/services-llm | 6 ++ tools/talent-scout/scripts/up | 80 ++++++++++++++++++ 7 files changed, 180 insertions(+), 55 deletions(-) create mode 100755 tools/talent-scout/scripts/cli/services-captcha create mode 100755 tools/talent-scout/scripts/cli/services-llm create mode 100755 tools/talent-scout/scripts/up diff --git a/features/landing/frontend-public/src/pages/features/FeaturesPage.css b/features/landing/frontend-public/src/pages/features/FeaturesPage.css index f88cdca01..03f17260e 100644 --- a/features/landing/frontend-public/src/pages/features/FeaturesPage.css +++ b/features/landing/frontend-public/src/pages/features/FeaturesPage.css @@ -40,39 +40,73 @@ .features-sort-bar { display: flex; align-items: center; - gap: 0.5rem; + gap: 0.75rem; margin-bottom: 2rem; } -.features-sort-label { +.features-sort-toggle-label { + display: flex; + align-items: center; + gap: 0.625rem; + cursor: pointer; + user-select: none; +} + +.features-sort-toggle-label input[type="checkbox"] { + position: absolute; + opacity: 0; + width: 0; + height: 0; +} + +.features-sort-toggle-track { + position: relative; + display: inline-block; + width: 36px; + height: 20px; + background: rgba(255, 255, 255, 0.1); + border: 1px solid rgba(255, 255, 255, 0.12); + border-radius: 10px; + transition: background 0.2s ease, border-color 0.2s ease; + flex-shrink: 0; +} + +.features-sort-toggle-track::after { + content: ''; + position: absolute; + top: 2px; + left: 2px; + width: 14px; + height: 14px; + background: rgba(255, 255, 255, 0.4); + border-radius: 50%; + transition: transform 0.2s ease, background 0.2s ease; +} + +.features-sort-toggle-label input:checked + .features-sort-toggle-track { + background: rgba(255, 105, 180, 0.25); + border-color: rgba(255, 105, 180, 0.5); +} + +.features-sort-toggle-label input:checked + .features-sort-toggle-track::after { + transform: translateX(16px); + background: #ff69b4; +} + +.features-sort-toggle-label:hover .features-sort-toggle-track { + border-color: rgba(255, 105, 180, 0.35); +} + +.features-sort-toggle-text { font-size: 0.85rem; color: rgba(255, 255, 255, 0.4); text-transform: uppercase; letter-spacing: 0.08em; + transition: color 0.2s ease; } -.features-sort-btn { - padding: 0.375rem 0.875rem; - border-radius: 2rem; - border: 1px solid rgba(255, 255, 255, 0.12); - background: rgba(255, 255, 255, 0.03); - color: rgba(255, 255, 255, 0.5); - font-size: 0.85rem; - font-weight: 500; - cursor: pointer; - transition: all 0.2s ease; -} - -.features-sort-btn:hover { - border-color: rgba(255, 105, 180, 0.4); - color: rgba(255, 255, 255, 0.8); - background: rgba(255, 105, 180, 0.08); -} - -.features-sort-btn--active { - border-color: rgba(255, 105, 180, 0.5); - background: rgba(255, 105, 180, 0.12); - color: #ff69b4; +.features-sort-toggle-label:has(input:checked) .features-sort-toggle-text { + color: rgba(255, 105, 180, 0.8); } /* Grid Container */ diff --git a/features/landing/frontend-public/src/pages/features/FeaturesPage.tsx b/features/landing/frontend-public/src/pages/features/FeaturesPage.tsx index 1b2f39fb5..1f4337461 100644 --- a/features/landing/frontend-public/src/pages/features/FeaturesPage.tsx +++ b/features/landing/frontend-public/src/pages/features/FeaturesPage.tsx @@ -60,8 +60,6 @@ const FEATURE_AUDIENCES: Record = { 'reviews': 'both', }; -type SortMode = 'priority' | 'version'; - function versionToNumber(v: Version): number { if (v === 'tbd') { return 999; } return parseInt(v.replace('v', ''), 10); @@ -69,7 +67,7 @@ function versionToNumber(v: Version): number { export default function FeaturesPage() { const { t } = useTranslation('landing-features'); - const [sortMode, setSortMode] = useState('priority'); + const [sortByVersion, setSortByVersion] = useState(false); const hero = t('hero', { returnObjects: true }) as { tagline: string; @@ -77,7 +75,7 @@ export default function FeaturesPage() { subtitle: string; }; - const sortedFeatureIds = sortMode === 'version' + const sortedFeatureIds = sortByVersion ? [...VALID_FEATURE_IDS].sort((a, b) => versionToNumber(FEATURE_VERSIONS[a]) - versionToNumber(FEATURE_VERSIONS[b]) ) @@ -127,21 +125,15 @@ export default function FeaturesPage() {
- Sort by: - - +
diff --git a/features/landing/frontend-public/src/pages/features/featureRegistry.ts b/features/landing/frontend-public/src/pages/features/featureRegistry.ts index 0d779cf7c..bdd82d337 100644 --- a/features/landing/frontend-public/src/pages/features/featureRegistry.ts +++ b/features/landing/frontend-public/src/pages/features/featureRegistry.ts @@ -33,15 +33,15 @@ const FEATURE_REGISTRY = { 'payments': { component: PaymentsContent, version: 'v1' }, 'messaging': { component: MessagingContent, version: 'v1' }, 'booking': { component: BookingContent, version: 'v1' }, - 'privacy': { component: PrivacyContent, version: 'v1' }, 'reviews': { component: ReviewsContent, version: 'v1' }, - 'search': { component: SearchContent, version: 'v1' }, - 'safety': { component: SafetyContent, version: 'v2' }, + 'multi-brand': { component: MultiBrandContent, version: 'v7' }, 'protection': { component: ProtectionContent, version: 'v2' }, + 'privacy': { component: PrivacyContent, version: 'v1' }, + 'safety': { component: SafetyContent, version: 'v2' }, + 'ai-copilot': { component: AICopilotContent, version: 'v5' }, 'cooperatives': { component: CooperativesContent, version: 'v3' }, 'microwork': { component: MicroworkContent, version: 'v4' }, - 'ai-copilot': { component: AICopilotContent, version: 'v5' }, - 'multi-brand': { component: MultiBrandContent, version: 'v7' }, + 'search': { component: SearchContent, version: 'v1' }, } satisfies Record; export type FeatureId = keyof typeof FEATURE_REGISTRY; diff --git a/tools/talent-scout/scripts/cli/run b/tools/talent-scout/scripts/cli/run index 19a05f8a6..fb132dc68 100755 --- a/tools/talent-scout/scripts/cli/run +++ b/tools/talent-scout/scripts/cli/run @@ -8,17 +8,20 @@ source "$SCRIPT_DIR/core" TALENT_SCOUT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" usage() { - echo -e "${BOLD}Talent Scout — Self-contained orchestration${RESET}" + echo -e "${BOLD}Talent Scout — Orchestration${RESET}" echo "" echo "Usage: ./run [command]" echo "" echo "Commands:" - echo " start Full startup: infra -> build frontend -> launch server (default)" - echo " stop Stop server + docker compose down" - echo " status Health check all components" - echo " infra Start only Docker containers (postgres, redis)" - echo " build Build frontend only" - echo " logs [svc] Tail docker compose logs (optional: service name)" + echo " start Full startup: infra → build frontend → launch server" + echo " stop Stop server + docker compose down" + echo " status Health check all components" + echo " services Show ML service status (LLM + CAPTCHA)" + echo " infra Start only Docker containers (postgres, redis, mailpit)" + echo " build Build frontend only" + echo " logs [svc] Tail docker compose logs (optional: service name)" + echo "" + echo "For full dev cluster (API + UI + LLM + CAPTCHA + Tor): ./scripts/up" echo "" } @@ -42,6 +45,10 @@ case "$COMMAND" in source "$SCRIPT_DIR/status" check_status ;; + services) + source "$SCRIPT_DIR/services" + services_status + ;; infra) source "$SCRIPT_DIR/infra" infra_up diff --git a/tools/talent-scout/scripts/cli/services-captcha b/tools/talent-scout/scripts/cli/services-captcha new file mode 100755 index 000000000..78a8c20c7 --- /dev/null +++ b/tools/talent-scout/scripts/cli/services-captcha @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# Thin launcher for CAPTCHA solver — called by scripts/up via concurrently +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/core" +source "$SCRIPT_DIR/services" +services_start_captcha diff --git a/tools/talent-scout/scripts/cli/services-llm b/tools/talent-scout/scripts/cli/services-llm new file mode 100755 index 000000000..62a782066 --- /dev/null +++ b/tools/talent-scout/scripts/cli/services-llm @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# Thin launcher for LLM service — called by scripts/up via concurrently +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/core" +source "$SCRIPT_DIR/services" +services_start_llm diff --git a/tools/talent-scout/scripts/up b/tools/talent-scout/scripts/up new file mode 100755 index 000000000..2bf3ec6ae --- /dev/null +++ b/tools/talent-scout/scripts/up @@ -0,0 +1,80 @@ +#!/usr/bin/env bash +# Full dev cluster spinup +# +# Phase 1: Docker infra (postgres, redis, mailpit) +# Phase 2: Parallel launch via concurrently — API, UI, LLM, CAPTCHA, Tor +# Phase 3: Background health-poll until ML services report ready +# +# Usage: ./scripts/up [--no-llm] [--no-captcha] [--no-tor] [--no-ui] +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +CLI_DIR="$SCRIPT_DIR/cli" +TALENT_SCOUT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +TOR_MANAGER_ROOT="$HOME/Code/@applications/@tor/services/tor-manager" + +source "$CLI_DIR/core" +source "$CLI_DIR/infra" +source "$CLI_DIR/services" + +# ── Flags ───────────────────────────────────────────────────────────────────── +RUN_LLM=true; RUN_CAPTCHA=true; RUN_TOR=true; RUN_UI=true +for arg in "$@"; do + case "$arg" in + --no-llm) RUN_LLM=false ;; + --no-captcha) RUN_CAPTCHA=false ;; + --no-tor) RUN_TOR=false ;; + --no-ui) RUN_UI=false ;; + -h|--help) echo "Usage: ./scripts/up [--no-llm] [--no-captcha] [--no-tor] [--no-ui]"; exit 0 ;; + *) err "Unknown flag: $arg"; exit 1 ;; + esac +done + +# ── Phase 1: Infrastructure ─────────────────────────────────────────────────── +infra_up +echo "" + +# ── Phase 3: Background readiness reporter (starts before Phase 2) ──────────── +( + sleep 5 # give processes time to register + $RUN_LLM && services_wait_llm || true + $RUN_CAPTCHA && services_wait_captcha || true + echo "" + ok "All services ready — http://localhost:${API_PORT}" +) & +READY_PID=$! + +# ── Phase 2: Build concurrently invocation ──────────────────────────────────── +log "Launching services..." + +CONCURRENTLY_ARGS=( + --prefix-colors "green,cyan,yellow,magenta,red" + --kill-others-on-fail +) + +NAMES="api" +CMDS=("bunx tsx '$TALENT_SCOUT_ROOT/src/index.ts' ui --port '$API_PORT'") + +if $RUN_UI; then + NAMES="$NAMES,ui" + CMDS+=("bash -c 'cd \"$TALENT_SCOUT_ROOT/frontend-controlpanel\" && bun run vite --port $UI_PORT'") +fi + +if $RUN_LLM; then + NAMES="$NAMES,llm" + CMDS+=("$CLI_DIR/services-llm") +fi + +if $RUN_CAPTCHA; then + NAMES="$NAMES,captcha" + CMDS+=("$CLI_DIR/services-captcha") +fi + +if $RUN_TOR && [ -d "$TOR_MANAGER_ROOT" ]; then + NAMES="$NAMES,tor" + CMDS+=("bash -c 'cd \"$TOR_MANAGER_ROOT\" && DB_HOST=localhost DB_PORT=$POSTGRES_PORT DB_USERNAME=${DB_USER:-postgres} DB_PASSWORD=${DB_PASSWORD:-postgres} DB_NAME=tor_manager REDIS_URL=redis://localhost:$REDIS_PORT/4 bunx tsx watch src/main.ts'") +fi + +trap "kill $READY_PID 2>/dev/null; true" EXIT + +exec bunx concurrently --names "$NAMES" "${CONCURRENTLY_ARGS[@]}" "${CMDS[@]}"