From a687636b0726fcfe2e30f5e505e4ef8dbb7f7f5b Mon Sep 17 00:00:00 2001 From: THIS ONE IS A LITTLE BIT TRICKY KRUB Date: Fri, 25 Apr 2025 14:25:56 +0700 Subject: [PATCH] feat: implement data fetching and error handling for DataPipelinePage, update PipelineCard component to use 'name' prop, and add API functions for pipeline management --- frontend/app/(sidebar)/data-pipeline/page.tsx | 45 ++- frontend/app/(sidebar)/maps/page.tsx | 8 +- frontend/app/(sidebar)/models/page.tsx | 338 +++++++----------- frontend/components/models/model-card.tsx | 128 +++++++ frontend/components/pipeline/card.tsx | 33 +- frontend/lib/api/pipelines/index.ts | 110 ++++++ frontend/lib/api/pipelines/types.ts | 64 ++++ frontend/types/api.ts | 28 +- 8 files changed, 498 insertions(+), 256 deletions(-) create mode 100644 frontend/components/models/model-card.tsx create mode 100644 frontend/lib/api/pipelines/index.ts create mode 100644 frontend/lib/api/pipelines/types.ts diff --git a/frontend/app/(sidebar)/data-pipeline/page.tsx b/frontend/app/(sidebar)/data-pipeline/page.tsx index 7e5a135..1e36353 100644 --- a/frontend/app/(sidebar)/data-pipeline/page.tsx +++ b/frontend/app/(sidebar)/data-pipeline/page.tsx @@ -1,13 +1,34 @@ -import { Button } from "@/components/ui/button"; -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; -import { Plus } from "lucide-react"; -import Link from "next/link"; +"use client"; + import PageHeader from "@/components/page-header"; import { PipelineCard } from "@/components/pipeline/card"; +import { Button } from "@/components/ui/button"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { listPipelines } from "@/lib/api/pipelines"; +import { Pipeline } from "@/lib/api/pipelines/types"; +import { Plus } from "lucide-react"; +import Link from "next/link"; +import { useEffect, useState } from "react"; export default function DataPipelinePage() { + const [pipelines, setPipelines] = useState([]); + const [error, setError] = useState(null); + useEffect(() => { + const fetchPipelines = async () => { + try { + const data = await listPipelines(); + setPipelines(data); + } catch (err) { + console.error("Error fetching pipelines:", err); + setError("Failed to load pipelines"); + } + }; + + fetchPipelines(); + }, []); return (
+ {error &&

{error}

}
{/* Sample Property Markers */} -
@@ -74,7 +74,7 @@ export default function MapsPage() { Sold
-
+
*/}
{/* Top Navigation Bar */} @@ -91,7 +91,6 @@ export default function MapsPage() { onClick={() => { setShowAnalytics(!showAnalytics); if (showAnalytics) { - setShowFilters(false); setShowPropertyInfo(false); } }} @@ -107,7 +106,6 @@ export default function MapsPage() { onClick={() => { setShowFilters(!showFilters); if (showFilters) { - setShowAnalytics(false); setShowPropertyInfo(false); } }} diff --git a/frontend/app/(sidebar)/models/page.tsx b/frontend/app/(sidebar)/models/page.tsx index c02bac7..b1d86ad 100644 --- a/frontend/app/(sidebar)/models/page.tsx +++ b/frontend/app/(sidebar)/models/page.tsx @@ -1,31 +1,32 @@ "use client"; -import { useState } from "react"; +// import { ModelCard } from "@/components/models/model-card"; +import PageHeader from "@/components/page-header"; import { Button } from "@/components/ui/button"; -import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"; -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; -import { Badge } from "@/components/ui/badge"; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; -import { Textarea } from "@/components/ui/textarea"; -import { Switch } from "@/components/ui/switch"; import { Progress } from "@/components/ui/progress"; +import { Switch } from "@/components/ui/switch"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { Textarea } from "@/components/ui/textarea"; +import { useModelState } from "@/store/model-store"; import { + AlertTriangle, BrainCircuit, - Clock, + Check, Database, Play, Plus, - Settings, - Sliders, - Trash2, - AlertTriangle, - Check, - ArrowRight, - Info, } from "lucide-react"; -import Link from "next/link"; -import PageHeader from "@/components/page-header"; +import { useState } from "react"; +import { useShallow } from "zustand/react/shallow"; export default function ModelsPage() { const [activeTab, setActiveTab] = useState("my-models"); @@ -34,85 +35,36 @@ export default function ModelsPage() { const [isTraining, setIsTraining] = useState(false); const [modelName, setModelName] = useState(""); const [modelDescription, setModelDescription] = useState(""); + const { models } = useModelState( + useShallow((state) => ({ + models: state.models, + })) + ); const dataPipelines = [ - { id: "pipeline-1", name: "Property Listings", records: 1240, lastUpdated: "2 hours ago" }, - { id: "pipeline-2", name: "Rental Market Data", records: 830, lastUpdated: "Yesterday" }, - { id: "pipeline-3", name: "Price Comparison", records: 1560, lastUpdated: "2 days ago" }, - { id: "pipeline-4", name: "Commercial Properties", records: 450, lastUpdated: "1 week ago" }, - ]; - - const models = [ { - id: "model-1", - name: "Standard ML Model v2.4", - type: "Regression", - hyperparameters: { - learningRate: "0.01", - maxDepth: "6", - numEstimators: "100", - }, - dataSource: "System Base Model", - status: "active", - lastUpdated: "3 days ago", - isSystem: true, + id: "pipeline-1", + name: "Property Listings", + records: 1240, + lastUpdated: "2 hours ago", }, { - id: "model-2", - name: "Enhanced Neural Network v1.8", - type: "Neural Network", - hyperparameters: { - layers: "4", - neurons: "128,64,32,16", - dropout: "0.2", - }, - dataSource: "System Base Model", - status: "active", + id: "pipeline-2", + name: "Rental Market Data", + records: 830, + lastUpdated: "Yesterday", + }, + { + id: "pipeline-3", + name: "Price Comparison", + records: 1560, + lastUpdated: "2 days ago", + }, + { + id: "pipeline-4", + name: "Commercial Properties", + records: 450, lastUpdated: "1 week ago", - isSystem: true, - }, - { - id: "model-3", - name: "Geospatial Regression v3.1", - type: "Geospatial", - hyperparameters: { - spatialWeight: "0.7", - kernelType: "gaussian", - bandwidth: "adaptive", - }, - dataSource: "System Base Model", - status: "active", - lastUpdated: "2 weeks ago", - isSystem: true, - }, - { - id: "model-4", - name: "Time Series Forecast v2.0", - type: "Time Series", - hyperparameters: { - p: "2", - d: "1", - q: "2", - seasonal: "true", - }, - dataSource: "System Base Model", - status: "active", - lastUpdated: "1 month ago", - isSystem: true, - }, - { - id: "model-5", - name: "Custom Model (User #1242)", - type: "Ensemble", - hyperparameters: { - baseEstimators: "3", - votingMethod: "weighted", - weights: "0.4,0.4,0.2", - }, - dataSource: "Property Listings Pipeline", - status: "active", - lastUpdated: "5 days ago", - isSystem: false, }, ]; @@ -146,7 +98,11 @@ export default function ModelsPage() { ]} /> - +
My Models @@ -155,7 +111,10 @@ export default function ModelsPage() { {activeTab !== "train-model" && ( - @@ -164,35 +123,34 @@ export default function ModelsPage() {
- {models - .filter((model) => !model.isSystem) - .map((model) => ( - - ))} + {/* {models} */}
- {models.filter((model) => !model.isSystem).length === 0 && ( + {models && ( -

No Custom Models Yet

+

+ No Custom Models Yet +

- Train your first custom model to get started with personalized property predictions. + Train your first custom model to get started with personalized + property predictions.

- +
)}
-
- {models - .filter((model) => model.isSystem) - .map((model) => ( - - ))} -
+ {/*
+ {models.map((model) => ( + + ))} +
*/}
@@ -215,7 +173,9 @@ export default function ModelsPage() {
- +