diff --git a/package-lock.json b/package-lock.json index 2196982..d0b6916 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,9 +8,12 @@ "name": "lynkeduppro-crm", "version": "0.1.0", "dependencies": { + "clsx": "^2.1.1", + "lucide-react": "^1.21.0", "next": "16.2.9", "react": "19.2.4", - "react-dom": "19.2.4" + "react-dom": "19.2.4", + "tailwind-merge": "^3.6.0" }, "devDependencies": { "@tailwindcss/postcss": "^4", @@ -2680,6 +2683,15 @@ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", "license": "MIT" }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -4970,6 +4982,15 @@ "yallist": "^3.0.2" } }, + "node_modules/lucide-react": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.21.0.tgz", + "integrity": "sha512-reEZMXq8Qdd5jg5XYkQ5TR1fB/GiQ7ih4vcrthYDtgjSDwh0i6/YLiGjsWsIwgN49gpAnd4J2elSNzncMEEUUQ==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -6181,6 +6202,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tailwind-merge": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.6.0.tgz", + "integrity": "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, "node_modules/tailwindcss": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.1.tgz", diff --git a/package.json b/package.json index aae156d..c12422c 100644 --- a/package.json +++ b/package.json @@ -9,9 +9,12 @@ "lint": "eslint" }, "dependencies": { + "clsx": "^2.1.1", + "lucide-react": "^1.21.0", "next": "16.2.9", "react": "19.2.4", - "react-dom": "19.2.4" + "react-dom": "19.2.4", + "tailwind-merge": "^3.6.0" }, "devDependencies": { "@tailwindcss/postcss": "^4", diff --git a/src/app/dashboard/layout.tsx b/src/app/dashboard/layout.tsx new file mode 100644 index 0000000..be6e634 --- /dev/null +++ b/src/app/dashboard/layout.tsx @@ -0,0 +1,14 @@ +import { Sidebar } from "@/components/layout/sidebar"; + +export default function DashboardLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( +
+ +
{children}
+
+ ); +} diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx new file mode 100644 index 0000000..c40de61 --- /dev/null +++ b/src/app/dashboard/page.tsx @@ -0,0 +1,41 @@ +import type { Metadata } from "next"; +import { Header } from "@/components/layout/header"; + +export const metadata: Metadata = { + title: "Dashboard", +}; + +const stats = [ + { label: "Total Leads", value: "0" }, + { label: "Open Deals", value: "0" }, + { label: "Contacts", value: "0" }, + { label: "Revenue", value: "$0" }, +]; + +export default function DashboardPage() { + return ( + <> +
+
+
+ {stats.map((stat) => ( +
+

{stat.label}

+

{stat.value}

+
+ ))} +
+ +
+

+ Yahan pages add karenge — Leads, Contacts, Deals, Tasks. Aap batao + kaunsa page pehle banana hai. +

+
+
+ + ); +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 976eb90..3622122 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,5 +1,6 @@ import type { Metadata } from "next"; import { Geist, Geist_Mono } from "next/font/google"; +import { siteConfig } from "@/config/site"; import "./globals.css"; const geistSans = Geist({ @@ -13,8 +14,11 @@ const geistMono = Geist_Mono({ }); export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: { + default: siteConfig.name, + template: `%s | ${siteConfig.shortName}`, + }, + description: siteConfig.description, }; export default function RootLayout({ diff --git a/src/app/page.tsx b/src/app/page.tsx index 3f36f7c..6fcc55b 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,65 +1,24 @@ -import Image from "next/image"; +import Link from "next/link"; +import { siteConfig } from "@/config/site"; export default function Home() { return ( -
-
- Next.js logo -
-

- To get started, edit the page.tsx file. -

-

- Looking for a starting point or more instructions? Head over to{" "} - - Templates - {" "} - or the{" "} - - Learning - {" "} - center. -

-
-
- - Vercel logomark - Deploy Now - - - Documentation - -
-
-
+
+ + {siteConfig.shortName} + +

+ {siteConfig.name} +

+

+ {siteConfig.description} +

+ + Go to Dashboard → + +
); } diff --git a/src/components/layout/header.tsx b/src/components/layout/header.tsx new file mode 100644 index 0000000..288cf9a --- /dev/null +++ b/src/components/layout/header.tsx @@ -0,0 +1,10 @@ +export function Header({ title }: { title: string }) { + return ( +
+

{title}

+
+
+
+
+ ); +} diff --git a/src/components/layout/sidebar.tsx b/src/components/layout/sidebar.tsx new file mode 100644 index 0000000..f472ff6 --- /dev/null +++ b/src/components/layout/sidebar.tsx @@ -0,0 +1,38 @@ +"use client"; + +import Link from "next/link"; +import { usePathname } from "next/navigation"; +import { siteConfig, navItems } from "@/config/site"; +import { cn } from "@/lib/utils"; + +export function Sidebar() { + const pathname = usePathname(); + + return ( + + ); +} diff --git a/src/config/site.ts b/src/config/site.ts new file mode 100644 index 0000000..1d9e888 --- /dev/null +++ b/src/config/site.ts @@ -0,0 +1,18 @@ +export const siteConfig = { + name: "LynkedUpPro CRM", + shortName: "LynkedUpPro", + description: "CRM to manage leads, contacts, deals and your sales pipeline.", + url: "https://lynkeduppro.com", +}; + +export type NavItem = { + title: string; + href: string; + icon?: string; +}; + +/** Sidebar / main navigation. Add page routes here as we build them. */ +export const navItems: NavItem[] = [ + { title: "Dashboard", href: "/dashboard", icon: "LayoutDashboard" }, + // pages aayenge yahan: Leads, Contacts, Deals, Tasks, Settings ... +]; diff --git a/src/lib/utils.ts b/src/lib/utils.ts new file mode 100644 index 0000000..3e491e3 --- /dev/null +++ b/src/lib/utils.ts @@ -0,0 +1,26 @@ +import { clsx, type ClassValue } from "clsx"; +import { twMerge } from "tailwind-merge"; + +/** + * Merge Tailwind class names safely (handles conditional + conflicting classes). + */ +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} + +/** Format a number as currency (default: USD). */ +export function formatCurrency(value: number, currency = "USD") { + return new Intl.NumberFormat("en-US", { + style: "currency", + currency, + }).format(value); +} + +/** Format a date into a readable short form. */ +export function formatDate(date: Date | string) { + return new Intl.DateTimeFormat("en-US", { + day: "2-digit", + month: "short", + year: "numeric", + }).format(new Date(date)); +} diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 0000000..3814263 --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,30 @@ +/** Shared domain types for the CRM. Extend as features are added. */ + +export type ID = string; + +export type Lead = { + id: ID; + name: string; + email: string; + phone?: string; + company?: string; + status: "new" | "contacted" | "qualified" | "lost" | "won"; + createdAt: string; +}; + +export type Contact = { + id: ID; + name: string; + email: string; + phone?: string; + company?: string; +}; + +export type Deal = { + id: ID; + title: string; + amount: number; + stage: "prospect" | "negotiation" | "proposal" | "closed-won" | "closed-lost"; + contactId?: ID; + createdAt: string; +};