diff --git a/README.md b/README.md index f431046..9e2133a 100644 --- a/README.md +++ b/README.md @@ -40,14 +40,27 @@ A 360-degree view of your territory's health. --- -## 👥 USER ROLES & DEMO ACCOUNTS +## � KEY FEATURES (Latest Updates) -To explore the platform, use these pre-configured accounts. +### 🎨 "LynkedUp Pro" Branding & UX +- **Smooth Animations**: Global page transitions (Fade/Slide) and silky-smooth collapsible sidebar. +- **Visual Polish**: Glassmorphism everywhere, custom "LynkedUp" loaders, and pulsing interactive elements. +- **Dark Mode**: Fully supported system-wide dark mode with inverted map tiles for comfortable night viewing. + +### 🌍 Advanced Mapping +- **Lead Creation**: Click anywhere on the map to reverse-geocode addresses and create new leads on the fly. +- **Polygon Visualization**: Color-coded property footprints indicating status (Hot Lead, Customer, etc.). + +--- + +## �👥 USER ROLES & DEMO ACCOUNTS + +To explore the platform, use these pre-configured accounts. **Password for ALL accounts is: `password`** ### 1. Field Agent (Worker) *The primary user. Can view maps, access detailed property data, and manage leads.* -- **Username/ID**: `EMP001` -- **Password**: `password123` +- **Username/ID**: `FA001` (Frank Agent) +- **Alternates**: `FA002`, `FA003`, `FA004`, `FA005` - **Role Capabilities**: - Access Dashboard & Widget Data. - View/Edit Lead Status (Hot, Cold, Customer). @@ -55,15 +68,15 @@ To explore the platform, use these pre-configured accounts. ### 2. Administrator *The manager. Sees all agents and global stats.* -- **Username/ID**: `ADMIN01` -- **Password**: `adminpass` +- **Username/ID**: `ADM01` (Adam Admin) +- **Alternates**: `ADM02`, `ADM03` - **Role Capabilities**: - All Agent capabilities + User Management (Mock). ### 3. Customer (Homeowner) *The client. Limited view of their own property.* -- **Username**: `john_doe` -- **Password**: `customer123` +- **Username**: `alice` +- **Alternates**: `bob`, `charlie` - **Role Capabilities**: - View personal property details. - Request Service. @@ -76,7 +89,7 @@ To explore the platform, use these pre-configured accounts. - **Frontend**: React 18 (Vite), Tailwind CSS, Glassmorphism UI. - **State**: `MockStore` (Simulates Backend/DB), `AuthContext` (Session Management). -- **AI Engine**: Groq SDK (`qwen-2.5-32b`) injected with dynamic system prompts. +- **AI Engine**: Groq SDK (`qwen-3-32b`) injected with dynamic system prompts. - **Visuals**: `react-leaflet` (Maps), `recharts` (Analytics), `lucide-react` (Icons). ### 🧠 Deep Dive: How It Works diff --git a/index.html b/index.html index 0f88619..e9e617b 100644 --- a/index.html +++ b/index.html @@ -5,27 +5,27 @@ - Plano Realty CRM + LynkedUp Pro - Next Gen Roofing CRM + content="The all-in-one geospatial platform for roofing professionals. Features real-time mapping, AI diagnoses, and instant estimates using LiDAR technology." /> - - - + + + - + content="The all-in-one geospatial platform for roofing professionals. Features real-time mapping, AI diagnoses, and instant estimates using LiDAR technology." /> + - - + + - + content="The all-in-one geospatial platform for roofing professionals. Features real-time mapping, AI diagnoses, and instant estimates using LiDAR technology." /> + diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 0000000..b87b8d3 --- /dev/null +++ b/netlify.toml @@ -0,0 +1,4 @@ +[[redirects]] + from = "/*" + to = "/index.html" + status = 200 diff --git a/public/og-logo.png b/public/og-logo.png new file mode 100644 index 0000000..8452a63 Binary files /dev/null and b/public/og-logo.png differ diff --git a/src/assets/images/LynkedUp_Pro_F_logo_Y.png b/src/assets/images/LynkedUp_Pro_F_logo_Y.png new file mode 100644 index 0000000..8452a63 Binary files /dev/null and b/src/assets/images/LynkedUp_Pro_F_logo_Y.png differ diff --git a/src/components/Chatbot.jsx b/src/components/Chatbot.jsx index 4607f89..6f2feae 100644 --- a/src/components/Chatbot.jsx +++ b/src/components/Chatbot.jsx @@ -259,7 +259,7 @@ ${scheduleSummary}`;
!isMinimized && setIsMinimized(!isMinimized)}>
-

Plano AI Assistant

+

LynkedUp AI

{/* Noise texture */}
-
-
-
- -
-
- Plano - Realty +
+
+ LynkedUp Pro +
+ LynkedUp + Pro
- - - -
-
+
+
-
+

{user?.name}

{user?.role?.replace('_', ' ').toLowerCase()}

@@ -144,17 +158,20 @@ const Layout = () => {
{/* Main Content */}
- + + +
diff --git a/src/components/Loader.jsx b/src/components/Loader.jsx new file mode 100644 index 0000000..073c682 --- /dev/null +++ b/src/components/Loader.jsx @@ -0,0 +1,38 @@ +import React from 'react'; +import Logo from '../assets/images/LynkedUp_Pro_F_logo_Y.png'; + +const Loader = ({ fullScreen = false, text = "Loading..." }) => { + const content = ( +
+
+ {/* Pulsing Ripple Effect */} +
+
+ Loading... +
+
+ {text && ( +
+

{text}

+
+
+
+
+
+
+ )} +
+ ); + + if (fullScreen) { + return ( +
+ {content} +
+ ); + } + + return
{content}
; +}; + +export default Loader; diff --git a/src/components/PageTransition.jsx b/src/components/PageTransition.jsx new file mode 100644 index 0000000..c7538e7 --- /dev/null +++ b/src/components/PageTransition.jsx @@ -0,0 +1,23 @@ +import React, { useEffect, useState } from 'react'; +import { useLocation } from 'react-router-dom'; + +const PageTransition = ({ children }) => { + const location = useLocation(); + const [displayLocation, setDisplayLocation] = useState(location); + const [transitionStage, setTransitionStage] = useState('fadeIn'); + + // Simple Fade In animation on mount/route change + // Note: For complex exit animations, we'd need a more robust library like framer-motion. + // Given the constraints and desire for "speed", a quick fade-in is often best. + + return ( +
+ {children} +
+ ); +}; + +export default PageTransition; diff --git a/src/index.css b/src/index.css index 94d86a6..11a1e53 100644 --- a/src/index.css +++ b/src/index.css @@ -2,6 +2,34 @@ @tailwind components; @tailwind utilities; +@layer utilities { + .animate-in { + animation-duration: 0.5s; + animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); + animation-fill-mode: forwards; + } + + .fade-in { + opacity: 0; + animation-name: fadeIn; + } + + .slide-in-from-bottom-4 { + transform: translateY(1rem); + animation-name: slideInBottom; + } +} + +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +@keyframes slideInBottom { + from { transform: translateY(1rem); opacity: 0; } + to { transform: translateY(0); opacity: 1; } +} + :root { font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; line-height: 1.5; diff --git a/src/pages/Dashboard.jsx b/src/pages/Dashboard.jsx index 072cbdd..d122a1e 100644 --- a/src/pages/Dashboard.jsx +++ b/src/pages/Dashboard.jsx @@ -16,9 +16,20 @@ import { RevenueByNeighborhood } from '../components/dashboard/RevenueByNeighbor import { GoldenLeadsScatter } from '../components/dashboard/GoldenLeadsScatter'; import { WeatherRiskGauge } from '../components/dashboard/WeatherRiskGauge'; +import Loader from '../components/Loader'; + const Dashboard = () => { const { properties, meetings } = useMockStore(); const { user } = useAuth(); + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + // Simulate initial data fetch + const timer = setTimeout(() => setIsLoading(false), 800); + return () => clearTimeout(timer); + }, []); + + // --- Weather State (Lifted) --- const [weather, setWeather] = useState(null); @@ -104,6 +115,8 @@ const Dashboard = () => { .filter(m => new Date(m.date) < today) .sort((a, b) => new Date(b.date) - new Date(a.date)); // Most recent first + if (isLoading) return ; + return (
diff --git a/src/pages/Landing.jsx b/src/pages/Landing.jsx index 123588f..bb9bd67 100644 --- a/src/pages/Landing.jsx +++ b/src/pages/Landing.jsx @@ -8,6 +8,7 @@ import { SpotlightCard } from '../components/SpotlightCard'; import { ComparisonSlider } from '../components/ComparisonSlider'; import gsap from 'gsap'; import { ScrollTrigger } from 'gsap/ScrollTrigger'; +import Logo from '../assets/images/LynkedUp_Pro_F_logo_Y.png'; gsap.registerPlugin(ScrollTrigger); @@ -56,10 +57,8 @@ const Landing = () => {