diff --git a/frontend/app/(routes)/data-pipeline/create/page.tsx b/frontend/app/(routes)/data-pipeline/create/page.tsx
deleted file mode 100644
index a382632..0000000
--- a/frontend/app/(routes)/data-pipeline/create/page.tsx
+++ /dev/null
@@ -1,407 +0,0 @@
-import { Button } from "@/components/ui/button"
-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 { ArrowLeft, Globe, FileUp, DatabaseIcon, Plus, Trash2, BrainCircuit } from "lucide-react"
-import Link from "next/link"
-import PageHeader from "@/components/page-header"
-import { Badge } from "@/components/ui/badge"
-import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
-import { Switch } from "@/components/ui/switch"
-
-export default function CreatePipelinePage() {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
- Pipeline Details
- Basic information about your data pipeline
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Separate tags with commas
-
-
-
-
-
-
-
-
-
-
- AI Assistant
-
- Customize how AI processes your data
-
-
-
-
-
-
-
-
- Provide specific instructions to guide the AI in processing your data sources
-
-
-
-
-
-
-
-
Automatically identify price, location, etc.
-
-
-
-
-
-
-
-
- Get AI suggestions for matching fields across sources
-
-
-
-
-
-
-
-
-
Remove duplicate entries automatically
-
-
-
-
-
-
-
-
-
-
-
-
- Data Sources
- Add one or more data sources to your pipeline
-
-
-
-
-
-
-
- Website Source #1
-
-
-
-
-
-
-
-
-
-
-
-
-
- Pattern Detection
-
-
-
-
- Add multiple URLs from the same website (one per line)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- File Upload Source #1
-
-
-
-
-
-
-
-
-
- Drag and drop your file here, or click to browse
-
-
-
-
-
- Supported formats: CSV, JSON, Excel, XML (up to 50MB)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- API Source #1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Schedule & Automation
- Configure when and how your pipeline should run
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )
-}
-
diff --git a/frontend/app/(routes)/data-pipeline/page.tsx b/frontend/app/(routes)/data-pipeline/page.tsx
deleted file mode 100644
index 2acdf94..0000000
--- a/frontend/app/(routes)/data-pipeline/page.tsx
+++ /dev/null
@@ -1,242 +0,0 @@
-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 { Clock, Database, Play, Plus, RefreshCw, Pause, AlertTriangle, Copy } from "lucide-react"
-import Link from "next/link"
-import PageHeader from "@/components/page-header"
-
-export default function DataPipelinePage() {
- return (
-
-
-
-
-
-
- Active Pipelines
- Paused
- All Pipelines
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )
-}
-
-interface PipelineCardProps {
- title: string
- description: string
- status: "active" | "paused" | "error"
- lastRun: string
- nextRun: string
- sources: number
- records: number
- error?: string
- aiPowered?: boolean
-}
-
-function PipelineCard({
- title,
- description,
- status,
- lastRun,
- nextRun,
- sources,
- records,
- error,
- aiPowered,
-}: PipelineCardProps) {
- return (
-
-
-
- {title}
-
-
- {description}
-
-
-
-
-
- Last run:
- {lastRun}
-
-
-
- Next run:
- {nextRun}
-
-
-
- Sources:
- {sources}
- •
- Records:
- {records}
-
- {error && (
-
- )}
-
-
-
-
-
-
-
-
- {status === "active" ? (
-
- ) : (
-
- )}
-
-
-
-
- )
-}
-
-function StatusBadge({ status }: { status: "active" | "paused" | "error" }) {
- if (status === "active") {
- return (
-
- Active
-
- )
- } else if (status === "paused") {
- return Paused
- } else {
- return Error
- }
-}
-
diff --git a/frontend/app/(routes)/data-pipeline/property-listings/page.tsx b/frontend/app/(routes)/data-pipeline/property-listings/page.tsx
deleted file mode 100644
index 66f1370..0000000
--- a/frontend/app/(routes)/data-pipeline/property-listings/page.tsx
+++ /dev/null
@@ -1,687 +0,0 @@
-import { Button } from "@/components/ui/button"
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
-import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
-import { Badge } from "@/components/ui/badge"
-import { ArrowLeft, Download, Edit, Play, Trash, Copy, Check, Plus } from "lucide-react"
-import Link from "next/link"
-import PageHeader from "@/components/page-header"
-import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
-import { Input } from "@/components/ui/input"
-import { Label } from "@/components/ui/label"
-
-export default function PipelineDetailsPage() {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Pipeline Status
-
-
-
-
- Status:
-
- Active
-
-
-
- Last Run:
- 2 hours ago
-
-
- Next Run:
- Tomorrow at 9:00 AM
-
-
- Run Frequency:
- Daily
-
-
- Total Records:
- 1,240
-
-
-
-
-
-
-
- Data Sources
-
-
-
-
-
- example-realty.com
- Website
-
-
Last updated: 2 hours ago
-
540 records
-
-
-
-
- property-listings.com
- Website
-
-
Last updated: 2 hours ago
-
420 records
-
-
-
-
- real-estate-api.com
- API
-
-
Last updated: 2 hours ago
-
280 records
-
-
-
-
-
-
-
- Export Options
-
-
-
-
-
-
-
-
-
- Export as JSON
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Export as CSV
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Export as SQLite
-
-
-
-
-
-
-
-
-
-
-
-
-
- Export as YAML
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Data Schema
- Data Preview
- Output Configuration
- Run History
- Settings
-
-
-
-
-
-
-
- Data Schema & Field Management
- Customize fields detected from your data sources
-
-
-
-
-
-
-
Detected Fields
-
-
-
-
-
-
-
-
-
-
- Auto-detected
-
-
Property title or name
-
-
-
-
-
-
-
-
-
- Auto-detected
-
-
Property price
-
-
-
-
-
-
-
-
-
- Auto-detected
-
-
Property location
-
-
-
-
-
-
-
-
-
- Auto-detected
-
-
Number of bedrooms
-
-
-
-
-
-
-
-
-
- Auto-detected
-
-
Number of bathrooms
-
-
-
-
-
-
-
-
-
-
-
-
- Create calculated fields
- Use formulas to generate new fields from existing data
-
-
-
-
-
-
- Derived
-
-
- Formula:
- price / squareFeet
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Data Preview
- Sample of the collected data
-
-
-
-
-
-
- | ID |
- Title |
- Price |
- Bedrooms |
- Bathrooms |
- Location |
- Sq. Ft. |
-
-
-
-
- | P001 |
- Modern Apartment |
- $350,000 |
- 2 |
- 2 |
- Downtown |
- 1,200 |
-
-
- | P002 |
- Luxury Villa |
- $1,250,000 |
- 5 |
- 4 |
- Suburbs |
- 3,500 |
-
-
- | P003 |
- Cozy Studio |
- $180,000 |
- 1 |
- 1 |
- City Center |
- 650 |
-
-
-
-
-
-
-
-
-
-
-
- Output Configuration
- Configure how your data will be structured and exported
-
-
-
-
-
-
-
-
- JSON
-
-
-
Structured data format
-
-
-
CSV
-
Spreadsheet compatible
-
-
-
SQLite
-
Portable database
-
-
-
YAML
-
Human-readable format
-
-
-
-
-
-
-
- Sample Data
-
-
-
- {`{
- "properties": [
- {
- "id": "P001",
- "title": "Modern Apartment",
- "price": 350000,
- "bedrooms": 2,
- "location": "Downtown"
- },
- {
- "id": "P002",
- "title": "Luxury Villa",
- "price": 1250000,
- "bedrooms": 5,
- "location": "Suburbs"
- }
- ]
-}`}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Run History
- History of pipeline executions
-
-
-
-
-
-
-
- | Run ID |
- Date |
- Status |
- Duration |
- Records |
- Actions |
-
-
-
-
- | RUN-123 |
- Today, 10:30 AM |
-
-
- Success
-
- |
- 2m 15s |
- 1,240 |
-
-
- |
-
-
- | RUN-122 |
- Yesterday, 10:30 AM |
-
-
- Success
-
- |
- 2m 10s |
- 1,235 |
-
-
- |
-
-
- | RUN-121 |
- 2 days ago, 10:30 AM |
-
-
- Success
-
- |
- 2m 05s |
- 1,228 |
-
-
- |
-
-
-
-
-
-
-
-
-
-
-
-
- Pipeline Settings
- Configure pipeline behavior
-
-
-
-
-
Scheduling
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )
-}
-
diff --git a/frontend/app/(routes)/maps/page.tsx b/frontend/app/(routes)/maps/page.tsx
deleted file mode 100644
index a1f6c89..0000000
--- a/frontend/app/(routes)/maps/page.tsx
+++ /dev/null
@@ -1,654 +0,0 @@
-"use client"
-
-import { useState, useRef } from "react"
-import { Button } from "@/components/ui/button"
-import { Card, CardContent } from "@/components/ui/card"
-import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
-import { Badge } from "@/components/ui/badge"
-import { Slider } from "@/components/ui/slider"
-import { Switch } from "@/components/ui/switch"
-import {
- MapPin,
- Home,
- BarChart2,
- Filter,
- MessageCircle,
- X,
- Plus,
- Minus,
- Droplets,
- Wind,
- Sun,
- LineChart,
- Send,
- Newspaper,
- Building,
- BedDouble,
- Bath,
- Star,
- Clock,
- RefreshCw,
-} from "lucide-react"
-import Link from "next/link"
-import { TopNavigation } from "@/components/navigation/top-navigation"
-
-export default function MapsPage() {
- const [showFilters, setShowFilters] = useState(false)
- const [showAnalytics, setShowAnalytics] = useState(false)
- const [showChat, setShowChat] = useState(false)
- const [showPropertyInfo, setShowPropertyInfo] = useState(false)
- const [activeTab, setActiveTab] = useState("basic")
- const [priceRange, setPriceRange] = useState([5000000, 20000000])
- const [radius, setRadius] = useState(30)
- const [message, setMessage] = useState("")
- const [messages, setMessages] = useState([{ role: "assistant", content: "Hi! How can I help you today?" }])
- const [mapZoom, setMapZoom] = useState(14)
- const [selectedModel, setSelectedModel] = useState("Standard ML Model v2.4")
- const mapRef = useRef(null)
-
-
-
- const handleSendMessage = () => {
- if (message.trim()) {
- setMessages([...messages, { role: "user", content: message }])
- // Simulate AI response
- setTimeout(() => {
- setMessages((prev) => [
- ...prev,
- {
- role: "assistant",
- content:
- "I can provide information about properties in this area. Would you like to know about flood risks, air quality, or nearby amenities?",
- },
- ])
- }, 1000)
- setMessage("")
- }
- }
-
- const handleZoomIn = () => {
- setMapZoom((prev) => Math.min(prev + 1, 20))
- }
-
- const handleZoomOut = () => {
- setMapZoom((prev) => Math.max(prev - 1, 10))
- }
-
- const handlePropertyClick = () => {
- setShowPropertyInfo(true)
- setShowFilters(false)
- setShowChat(false)
- }
-
- return (
-
- {/* Map Container */}
-
- {/* Map Placeholder - In a real implementation, this would be a map component */}
-
-
- {/* Sample Property Markers */}
-
-
-
-
-
- {/* Top Navigation Bar */}
-
-
- {/* Map Controls */}
-
-
- {/* Map Overlay Controls */}
-
-
-
-
-
-
- {/* Property Info Panel */}
- {showPropertyInfo && (
-
-
-
-
- Property Details
-
-
-
-
-
-
-
-

-
- Condominium
-
- Premium
-
-
-
-
-
Modern Condominium
-
-
- Sukhumvit, Bangkok
-
-
-
-
-
- 3 Beds
-
-
-
- 2 Baths
-
-
-
- 150 m²
-
-
-
-
฿15,000,000
-
-
-
-
Environmental Factors
-
-
-
- Flood Risk
- Moderate
-
-
-
- Air Quality
- Poor
-
-
-
- Noise
- Low
-
-
-
-
-
-
Nearby Facilities
-
-
- BTS Phrom Phong
- 300m
-
-
- EmQuartier Mall
- 500m
-
-
- Benchasiri Park
- 700m
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )}
-
- {/* Analytics Panel */}
- {showAnalytics && (
-
-
-
-
- Analytics
-
-
-
-
-
-
-
-
-
Information in radius will be analyzed
-
- Using: {selectedModel}
-
-
-
-
-
-
-
- Area Price History
-
- 10,000,000 Baht
- Overall Price History of this area
-
-
- {/* Simple line chart simulation */}
-
-
-
-
-
-
-
-
-
-
- Price Prediction
-
- 15,000,000 Baht
- The estimated price based on various factors.
-
-
- {/* Simple line chart simulation */}
-
-
-
-
-
-
-
-
-
-
-
- Flood Factor
- Moderate
-
-
-
-
-
-
-
-
- Air Factor
- Bad
-
-
-
-
-
- {/* Local News Section */}
-
-
-
- Local News
-
-
-
-
- New BTS Extension Planned
-
- The BTS Skytrain will be extended to cover more areas in Sukhumvit by 2025.
-
-
-
- 2 days ago
-
-
-
-
-
- Property Tax Changes
-
- New property tax regulations will take effect next month affecting luxury condominiums.
-
-
-
- 1 week ago
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )}
-
- {/* Filters Panel */}
- {showFilters && (
-
-
-
-
- Property Filters
-
-
-
-
-
-
-
-
- Basic
- Advanced
-
-
-
-
-
-
-
- setRadius(value[0])}
- className="flex-1"
- />
- {radius} km
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ฿{priceRange[0].toLocaleString()}
- ฿{priceRange[1].toLocaleString()}
-
-
setPriceRange(value)}
- />
-
-
-
-
-
-
- Low Flood Risk
-
-
-
-
- Good Air Quality
-
-
-
-
- Low Noise Pollution
-
-
-
-
-
-
-
-
-
-
-
- )}
-
- {/* Chat Panel */}
- {showChat && (
-
-
-
-
- Chat Assistant
-
-
-
-
-
-
-
- {messages.map((msg, index) => (
-
- ))}
-
-
-
-
- setMessage(e.target.value)}
- onKeyDown={(e) => {
- if (e.key === "Enter") handleSendMessage()
- }}
- />
-
-
-
-
- )}
-
- {/* Map Legend */}
-
-
- )
-}
-
diff --git a/frontend/app/(sidebar)/data-pipeline/create/create-pipeline-multiform.tsx b/frontend/app/(sidebar)/data-pipeline/create/create-pipeline-multiform.tsx
new file mode 100644
index 0000000..1f10c02
--- /dev/null
+++ b/frontend/app/(sidebar)/data-pipeline/create/create-pipeline-multiform.tsx
@@ -0,0 +1,126 @@
+"use client";
+
+import { AnimatePresence, motion } from "framer-motion";
+import { useState } from "react";
+import { useForm } from "react-hook-form";
+import { toast } from "sonner";
+
+import { AddDataSource } from "@/components/pipeline/add-data-source";
+import { PipelineAiAssistant } from "@/components/pipeline/ai-assistant";
+import { PipelineDetails } from "@/components/pipeline/details";
+import { ScheduleAndInformation } from "@/components/pipeline/schedule-and-information";
+import { PipelineSummary } from "@/components/pipeline/summary";
+import { Button } from "@/components/ui/button";
+import { Card, CardContent } from "@/components/ui/card";
+import { Form } from "@/components/ui/form";
+import { cn } from "@/lib/utils";
+import { pipelineSchema, PipelineFormValues } from "@/lib/validations/pipeline";
+import { zodResolver } from "@hookform/resolvers/zod";
+
+const TOTAL_STEPS = 5;
+
+const stepComponents = [
+ ,
+ ,
+ ,
+ ,
+ ,
+ ,
+];
+
+const motionVariants = {
+ enter: { opacity: 0, x: 50 },
+ center: { opacity: 1, x: 0 },
+ exit: { opacity: 0, x: -50 },
+};
+
+export default function CratePipelineForm() {
+ const [step, setStep] = useState(0);
+ const isFirstStep = step === 0;
+ const isLastStep = step === TOTAL_STEPS - 1;
+
+ const form = useForm({
+ resolver: zodResolver(pipelineSchema),
+ });
+ const { handleSubmit, reset } = form;
+
+ const onSubmit = async (formData: unknown) => {
+ if (!isLastStep) return setStep((s) => s + 1);
+ console.log(formData);
+ reset();
+ setStep(0);
+ toast.success("Form successfully submitted");
+ };
+
+ const handleBack = () => setStep((s) => (s > 0 ? s - 1 : s));
+
+ const StepForm = (
+
+
+ );
+
+ return (
+
+ {/* stepper */}
+
+ {Array.from({ length: TOTAL_STEPS }).map((_, index) => (
+
+
+ {index < TOTAL_STEPS - 1 && (
+
+ )}
+
+ ))}
+
+
+ {/* animated form */}
+
+
+
+
+ {StepForm}
+
+
+
+
+
+ );
+}
diff --git a/frontend/app/(sidebar)/data-pipeline/create/page.tsx b/frontend/app/(sidebar)/data-pipeline/create/page.tsx
new file mode 100644
index 0000000..a191786
--- /dev/null
+++ b/frontend/app/(sidebar)/data-pipeline/create/page.tsx
@@ -0,0 +1,24 @@
+import { Button } from "@/components/ui/button";
+import { ArrowLeft } from "lucide-react";
+import Link from "next/link";
+import CratePipelineForm from "./create-pipeline-multiform";
+
+export default function CreatePipelinePage() {
+ return (
+
+
+
+
+
+
+
+ {/*
+ */}
+
+
+
+ );
+}
diff --git a/frontend/app/(sidebar)/data-pipeline/page.tsx b/frontend/app/(sidebar)/data-pipeline/page.tsx
new file mode 100644
index 0000000..ccbb4b5
--- /dev/null
+++ b/frontend/app/(sidebar)/data-pipeline/page.tsx
@@ -0,0 +1,159 @@
+"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 { 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}
}
+
+
+
+
+
+ Active Pipelines
+ Paused
+ All Pipelines
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* mock pipeline card with data */}
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/frontend/app/(sidebar)/data-pipeline/property-listings/page.tsx b/frontend/app/(sidebar)/data-pipeline/property-listings/page.tsx
new file mode 100644
index 0000000..58ac495
--- /dev/null
+++ b/frontend/app/(sidebar)/data-pipeline/property-listings/page.tsx
@@ -0,0 +1,105 @@
+import { Button } from "@/components/ui/button";
+import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
+import { ArrowLeft, Edit, Play, Trash, Copy } from "lucide-react";
+import Link from "next/link";
+import PageHeader from "@/components/page-header";
+import { PipelineStatus } from "@/components/pipeline/status";
+import { PipelineDataSource } from "@/components/pipeline/data-source";
+import { PipelineExportData } from "@/components/pipeline/export-data";
+import { PipelineDataSchema } from "@/components/pipeline/data-schema";
+import { PipelineDataPreview } from "@/components/pipeline/data-preview";
+import { PipelineOutputConfig } from "@/components/pipeline/output-config";
+import { PipelineRunHistory } from "@/components/pipeline/run-history";
+import { PipelineSettings } from "@/components/pipeline/settings";
+
+export default function PipelineDetailsPage() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Data Schema
+ Data Preview
+ Output Configuration
+ Run History
+ Settings
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/frontend/app/(routes)/documentation/loading.tsx b/frontend/app/(sidebar)/documentation/loading.tsx
similarity index 100%
rename from frontend/app/(routes)/documentation/loading.tsx
rename to frontend/app/(sidebar)/documentation/loading.tsx
diff --git a/frontend/app/(routes)/documentation/models/page.tsx b/frontend/app/(sidebar)/documentation/models/page.tsx
similarity index 100%
rename from frontend/app/(routes)/documentation/models/page.tsx
rename to frontend/app/(sidebar)/documentation/models/page.tsx
diff --git a/frontend/app/(routes)/documentation/page.tsx b/frontend/app/(sidebar)/documentation/page.tsx
similarity index 100%
rename from frontend/app/(routes)/documentation/page.tsx
rename to frontend/app/(sidebar)/documentation/page.tsx
diff --git a/frontend/app/(sidebar)/layout.tsx b/frontend/app/(sidebar)/layout.tsx
new file mode 100644
index 0000000..39c730d
--- /dev/null
+++ b/frontend/app/(sidebar)/layout.tsx
@@ -0,0 +1,16 @@
+"use client";
+import Sidebar from "@/components/sidebar";
+
+export default function AppLayout({
+ children,
+}: Readonly<{
+ children: React.ReactNode;
+}>) {
+ return (
+
+ );
+
+}
\ No newline at end of file
diff --git a/frontend/app/(sidebar)/maps/page.tsx b/frontend/app/(sidebar)/maps/page.tsx
new file mode 100644
index 0000000..79caabf
--- /dev/null
+++ b/frontend/app/(sidebar)/maps/page.tsx
@@ -0,0 +1,186 @@
+"use client";
+
+import { AnalyticsPanel } from "@/components/map/analytics-panel";
+import { ChatPanel } from "@/components/map/chat-panel";
+import { FiltersPanel } from "@/components/map/filters-panel";
+import { PropertyInfoPanel } from "@/components/map/property-info-panel";
+
+import MapWithSearch from "@/components/map/map-with-search";
+import { TopNavigation } from "@/components/navigation/top-navigation";
+import { Button } from "@/components/ui/button";
+import { BarChart2, Filter, MessageCircle } from "lucide-react";
+import { useRef, useState } from "react";
+import Draggable from "react-draggable";
+
+export default function MapsPage() {
+ const [showFilters, setShowFilters] = useState(false);
+ const [showAnalytics, setShowAnalytics] = useState(false);
+ const [showChat, setShowChat] = useState(false);
+ const [showPropertyInfo, setShowPropertyInfo] = useState(false);
+ const analyticsRef = useRef(null);
+ const filtersRef = useRef(null);
+ const chatRef = useRef(null);
+ const propertyInfoRef = useRef(null);
+
+ const handlePropertyClick = () => {
+ setShowPropertyInfo(true);
+ setShowFilters(false);
+ setShowChat(false);
+ };
+
+ return (
+
+
+
+
+
+
+ {/* Sample Property Markers */}
+ {/*
+
+
*/}
+
+
+ {/* Top Navigation Bar */}
+
+
+ {/* Map Overlay Controls */}
+
+
+
+
+
+
+ {/* Property Info Panel */}
+ {showPropertyInfo && (
+
}>
+
+
+ )}
+
+ {/* Analytics Panel */}
+ {showAnalytics && (
+
}>
+
+
+ )}
+
+ {showFilters && (
+
}>
+
+
+
+
+ )}
+
+ {showChat && (
+
}>
+
+
+
+
+ )}
+
+ {/* Map Legend */}
+
+
+ );
+}
diff --git a/frontend/app/(routes)/models/page.tsx b/frontend/app/(sidebar)/models/page.tsx
similarity index 60%
rename from frontend/app/(routes)/models/page.tsx
rename to frontend/app/(sidebar)/models/page.tsx
index c02bac7..b1d86ad 100644
--- a/frontend/app/(routes)/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" && (
-
-
+