Files
rc-compat/bash-setup-scripts/setup-compatibility-option.sh

260 lines
8.4 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/zsh
echo "🛠 Setting up Compatibility Explorer (Option A)..."
COMPAT_DIR="src/app/compatibility"
mkdir -p "$COMPAT_DIR"
cat > "$COMPAT_DIR/page.js" << 'EOF'
"use client";
import { useEffect, useState } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { CATEGORIES } from "@/lib/data/categories";
function ModeCard({ title, emoji, description, children }) {
return (
<div className="border rounded-xl p-6 shadow-sm bg-white flex flex-col gap-4">
<div className="flex items-center gap-3">
<div className="text-2xl">{emoji}</div>
<div>
<h2 className="font-semibold text-lg">{title}</h2>
<p className="text-sm text-gray-500">{description}</p>
</div>
</div>
<div className="mt-2 flex flex-col gap-3">{children}</div>
</div>
);
}
export default function CompatibilityPage() {
const [models, setModels] = useState([]);
const [parts, setParts] = useState([]);
const [loading, setLoading] = useState(true);
const [modelForParts, setModelForParts] = useState("");
const [partForModels, setPartForModels] = useState("");
const [modelA, setModelA] = useState("");
const [modelB, setModelB] = useState("");
const [categoryModel, setCategoryModel] = useState("");
const [category, setCategory] = useState("");
const router = useRouter();
useEffect(() => {
async function load() {
try {
const [modelsRes, partsRes] = await Promise.all([
fetch("/api/models"),
fetch("/api/parts"),
]);
const modelsJson = modelsRes.ok ? await modelsRes.json() : [];
const partsJson = partsRes.ok ? await partsRes.json() : [];
setModels(modelsJson || []);
setParts(partsJson || []);
} catch (e) {
console.error("Failed to load models/parts", e);
} finally {
setLoading(false);
}
}
load();
}, []);
function handleGoToModelCompatibility() {
if (!modelForParts) return;
router.push(`/model/${modelForParts}`);
}
function handleGoToPartCompatibility() {
if (!partForModels) return;
router.push(`/part/${partForModels}`);
}
function handleExploreCategory() {
if (!categoryModel || !category) return;
router.push(`/category/${categoryModel}/${category}`);
}
function handleCompareModels() {
if (!modelA || !modelB) return;
// Stubbed for now to avoid broken routes
alert("Model comparison view coming soon! (Hotshot vs Supershot, etc.)");
}
return (
<div className="space-y-10">
{/* Breadcrumb-ish header */}
<nav className="text-sm text-gray-500">
<Link href="/" className="hover:underline text-blue-600">
Home
</Link>{" "}
<span></span>{" "}
<span className="font-semibold text-gray-700">Compatibility Explorer</span>
</nav>
{/* Page Title */}
<div>
<h1 className="text-4xl font-bold mb-2">Compatibility Explorer</h1>
<p className="text-gray-600 max-w-2xl">
Discover cross-compatibility between RC models and parts. Use one of the
tools below to explore fitment, upgrades, and shared components.
</p>
</div>
{loading && (
<p className="text-gray-500">Loading models and parts…</p>
)}
{/* Mode Selector Grid */}
{!loading && (
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{/* Mode 1: Model → Compatible Parts */}
<ModeCard
title="Model → Compatible Parts"
emoji="🔧"
description="Find every part that fits a specific RC model."
>
<select
className="border rounded-lg px-3 py-2"
value={modelForParts}
onChange={(e) => setModelForParts(e.target.value)}
>
<option value="">Select a model…</option>
{models.map((m) => (
<option key={m.id} value={m.id}>
{m.name} ({m.brand})
</option>
))}
</select>
<button
onClick={handleGoToModelCompatibility}
className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition disabled:opacity-50"
disabled={!modelForParts}
>
Show Compatible Parts
</button>
</ModeCard>
{/* Mode 2: Part → Compatible Models */}
<ModeCard
title="Part → Compatible Models"
emoji="🧩"
description="See all RC models that this part works with."
>
<select
className="border rounded-lg px-3 py-2"
value={partForModels}
onChange={(e) => setPartForModels(e.target.value)}
>
<option value="">Select a part…</option>
{parts.map((p) => (
<option key={p.id} value={p.id}>
{p.name} ({p.id})
</option>
))}
</select>
<button
onClick={handleGoToPartCompatibility}
className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition disabled:opacity-50"
disabled={!partForModels}
>
Show Compatible Models
</button>
</ModeCard>
{/* Mode 3: Compare Two Models (stubbed) */}
<ModeCard
title="Compare Two Models"
emoji="🔍"
description="See shared and unique parts between two models. (Coming soon)"
>
<div className="flex flex-col gap-2">
<select
className="border rounded-lg px-3 py-2"
value={modelA}
onChange={(e) => setModelA(e.target.value)}
>
<option value="">Select Model A…</option>
{models.map((m) => (
<option key={m.id} value={m.id}>
{m.name} ({m.brand})
</option>
))}
</select>
<select
className="border rounded-lg px-3 py-2"
value={modelB}
onChange={(e) => setModelB(e.target.value)}
>
<option value="">Select Model B…</option>
{models.map((m) => (
<option key={m.id} value={m.id}>
{m.name} ({m.brand})
</option>
))}
</select>
</div>
<button
onClick={handleCompareModels}
className="px-4 py-2 bg-gray-300 text-gray-700 rounded-lg cursor-not-allowed"
disabled
>
Compare (Coming Soon)
</button>
</ModeCard>
{/* Mode 4: Explore Categories */}
<ModeCard
title="Explore by Category"
emoji="📂"
description="Browse shocks, drivetrain, chassis, and more for a model."
>
<div className="flex flex-col gap-2">
<select
className="border rounded-lg px-3 py-2"
value={categoryModel}
onChange={(e) => setCategoryModel(e.target.value)}
>
<option value="">Select a model…</option>
{models.map((m) => (
<option key={m.id} value={m.id}>
{m.name} ({m.brand})
</option>
))}
</select>
<select
className="border rounded-lg px-3 py-2"
value={category}
onChange={(e) => setCategory(e.target.value)}
>
<option value="">Select a category…</option>
{CATEGORIES.map((cat) => (
<option key={cat} value={cat}>
{cat}
</option>
))}
</select>
</div>
<button
onClick={handleExploreCategory}
className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition disabled:opacity-50"
disabled={!categoryModel || !category}
>
Explore Category
</button>
</ModeCard>
</div>
)}
</div>
);
}
EOF
echo "🎉 Compatibility Explorer (Option A) page created at src/app/compatibility/page.js"