Initialize React dashboard project structure

Add initial project files for a modern React dashboard template using Vite. Includes documentation, configuration, and core frontend source files with sidebar layout, routing, and sample dashboard page.
This commit is contained in:
Juan Denis committed 2026-01-17 03:11:13 -05:00
1 parent 44a1dde4f4
commit 97a111feb7
17 files changed
+6141

No files matched your search

+1
View File
@@ -0,0 +1 @@
/frontend/node_modules
+482
View File
@@ -0,0 +1,482 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JuanPilot | Infrastructure</title>
<style>
/* --- DESIGN SYSTEM --- */
:root {
--bg-body: #09090b; /* Zinc 950 */
--bg-sidebar: #0f0f11; /* Slightly lighter than body */
--bg-card: #18181b; /* Zinc 900 */
--bg-hover: #27272a; /* Zinc 800 */
--border-subtle: #27272a;
--border-active: #3f3f46;
--text-primary: #f4f4f5;
--text-secondary: #a1a1aa;
--text-tertiary: #71717a;
--accent-primary: #6366f1; /* Indigo 500 */
--accent-glow: rgba(99, 102, 241, 0.15);
--success: #10b981;
--warning: #f59e0b;
--danger: #ef4444;
--font-main: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
--sidebar-width: 280px;
}
* { margin: 0; padding: 0; box-sizing: border-box; outline: none; }
body {
background-color: var(--bg-body);
color: var(--text-primary);
font-family: var(--font-main);
display: flex;
min-height: 100vh;
font-size: 14px;
line-height: 1.5;
}
/* --- ICONS (SVG Styling) --- */
svg {
width: 20px;
height: 20px;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
fill: none;
}
/* --- SIDEBAR --- */
.sidebar {
width: var(--sidebar-width);
background-color: var(--bg-sidebar);
border-right: 1px solid var(--border-subtle);
display: flex;
flex-direction: column;
position: fixed;
height: 100vh;
z-index: 10;
}
.brand {
padding: 24px 32px;
font-size: 16px;
font-weight: 700;
letter-spacing: -0.5px;
color: var(--text-primary);
display: flex;
align-items: center;
gap: 12px;
border-bottom: 1px solid var(--border-subtle);
}
.brand-logo {
width: 32px; height: 32px;
background: linear-gradient(135deg, var(--accent-primary), #818cf8);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
color: white;
}
.menu-label {
padding: 24px 32px 8px;
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--text-tertiary);
}
.nav { display: flex; flex-direction: column; padding: 0 16px; gap: 4px; }
.nav-item {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 16px;
color: var(--text-secondary);
text-decoration: none;
border-radius: 6px;
transition: all 0.2s ease;
font-weight: 500;
}
.nav-item:hover {
background-color: var(--bg-hover);
color: var(--text-primary);
}
.nav-item.active {
background-color: var(--accent-glow);
color: var(--accent-primary);
}
.user-profile {
margin-top: auto;
padding: 20px;
border-top: 1px solid var(--border-subtle);
display: flex;
align-items: center;
gap: 12px;
}
.avatar {
width: 36px; height: 36px;
background-color: var(--bg-hover);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: var(--text-secondary);
font-weight: 600;
}
/* --- MAIN AREA --- */
.main {
margin-left: var(--sidebar-width);
flex: 1;
padding: 40px;
}
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 40px;
}
h1 { font-size: 24px; font-weight: 600; letter-spacing: -0.5px; }
.subtitle { color: var(--text-tertiary); margin-top: 4px; }
.btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 10px 20px;
border-radius: 8px;
border: 1px solid transparent;
font-size: 13px;
font-weight: 500;
cursor: pointer;
transition: 0.2s;
}
.btn-primary {
background-color: var(--accent-primary);
color: white;
box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
}
.btn-primary:hover { background-color: #4f46e5; }
.btn-secondary {
background-color: transparent;
border-color: var(--border-active);
color: var(--text-primary);
}
.btn-secondary:hover { background-color: var(--bg-hover); }
/* --- GRID LAYOUT --- */
.dashboard-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
gap: 24px;
}
.card {
background-color: var(--bg-card);
border: 1px solid var(--border-subtle);
border-radius: 12px;
padding: 24px;
transition: transform 0.2s, border-color 0.2s;
position: relative;
overflow: hidden;
}
.card:hover {
border-color: var(--border-active);
transform: translateY(-2px);
}
.card-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 20px;
}
.app-icon {
width: 40px; height: 40px;
border-radius: 8px;
background-color: var(--bg-hover);
display: flex;
align-items: center;
justify-content: center;
color: var(--text-primary);
margin-bottom: 12px;
}
.status-badge {
display: flex;
align-items: center;
gap: 6px;
padding: 4px 10px;
border-radius: 20px;
font-size: 11px;
font-weight: 600;
border: 1px solid transparent;
}
.status-active { background: rgba(16, 185, 129, 0.1); color: var(--success); border-color: rgba(16, 185, 129, 0.2); }
.status-warning { background: rgba(245, 158, 11, 0.1); color: var(--warning); border-color: rgba(245, 158, 11, 0.2); }
.card h3 { font-size: 16px; font-weight: 600; color: var(--text-primary); margin-bottom: 4px; }
.card-link { color: var(--text-secondary); text-decoration: none; font-size: 13px; }
.card-link:hover { color: var(--accent-primary); }
.metric-row {
margin-top: 24px;
padding-top: 20px;
border-top: 1px solid var(--border-subtle);
display: flex;
justify-content: space-between;
font-size: 12px;
color: var(--text-secondary);
}
.metric-item { display: flex; flex-direction: column; gap: 4px; }
.metric-value { font-weight: 600; color: var(--text-primary); font-family: monospace; }
/* --- STATS BAR (CPU/RAM) --- */
.stats-strip {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 24px;
margin-bottom: 32px;
}
.stat-card {
background: var(--bg-card);
padding: 20px;
border-radius: 12px;
border: 1px solid var(--border-subtle);
display: flex;
flex-direction: column;
gap: 8px;
}
.stat-label { font-size: 12px; color: var(--text-tertiary); text-transform: uppercase; font-weight: 600; }
.stat-value { font-size: 20px; font-weight: 700; color: var(--text-primary); }
.progress-bar {
height: 4px;
background: var(--bg-hover);
border-radius: 2px;
overflow: hidden;
margin-top: 4px;
}
.progress-fill { height: 100%; border-radius: 2px; }
</style>
</head>
<body>
<aside class="sidebar">
<div class="brand">
<div class="brand-logo">
<svg viewBox="0 0 24 24"><path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"/></svg>
</div>
JuanPilot
</div>
<div class="menu-label">Overview</div>
<nav class="nav">
<a href="#" class="nav-item active">
<svg viewBox="0 0 24 24"><rect x="3" y="3" width="7" height="7"></rect><rect x="14" y="3" width="7" height="7"></rect><rect x="14" y="14" width="7" height="7"></rect><rect x="3" y="14" width="7" height="7"></rect></svg>
Dashboard
</a>
<a href="#" class="nav-item">
<svg viewBox="0 0 24 24"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline></svg>
Activity
</a>
</nav>
<div class="menu-label">Infrastructure</div>
<nav class="nav">
<a href="#" class="nav-item">
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"></circle><line x1="2" y1="12" x2="22" y2="12"></line><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path></svg>
Domains & Sites
</a>
<a href="#" class="nav-item">
<svg viewBox="0 0 24 24"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path><polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline><line x1="12" y1="22.08" x2="12" y2="12"></line></svg>
Applications
</a>
<a href="#" class="nav-item">
<svg viewBox="0 0 24 24"><ellipse cx="12" cy="5" rx="9" ry="3"></ellipse><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"></path><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"></path></svg>
Databases
</a>
<a href="#" class="nav-item">
<svg viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>
SSL Certificates
</a>
</nav>
<div class="menu-label">System</div>
<nav class="nav">
<a href="#" class="nav-item">
<svg viewBox="0 0 24 24"><path d="M4 17l6-6-6-6M12 19h8"/></svg>
Terminal / Logs
</a>
<a href="#" class="nav-item">
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
Settings
</a>
</nav>
<div class="user-profile">
<div class="avatar">JD</div>
<div style="font-size: 13px;">
<div style="font-weight: 600;">Juan Denis</div>
<div style="color: var(--text-tertiary);">Admin</div>
</div>
</div>
</aside>
<main class="main">
<header class="top-bar">
<div>
<h1>Dashboard</h1>
<div class="subtitle">Overview of your droplet status and applications.</div>
</div>
<div style="display: flex; gap: 12px;">
<button class="btn btn-secondary">
<svg viewBox="0 0 24 24"><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"></path></svg>
Logs
</button>
<button class="btn btn-primary">
<svg viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
New Application
</button>
</div>
</header>
<section class="stats-strip">
<div class="stat-card">
<div class="stat-label">CPU Usage</div>
<div class="stat-value">12%</div>
<div class="progress-bar"><div class="progress-fill" style="width: 12%; background: var(--success);"></div></div>
</div>
<div class="stat-card">
<div class="stat-label">Memory</div>
<div class="stat-value">1.8GB <span style="font-size: 14px; color: var(--text-tertiary);">/ 4GB</span></div>
<div class="progress-bar"><div class="progress-fill" style="width: 45%; background: var(--accent-primary);"></div></div>
</div>
<div class="stat-card">
<div class="stat-label">Disk Space</div>
<div class="stat-value">22GB <span style="font-size: 14px; color: var(--text-tertiary);">/ 80GB</span></div>
<div class="progress-bar"><div class="progress-fill" style="width: 27%; background: var(--accent-primary);"></div></div>
</div>
<div class="stat-card">
<div class="stat-label">Load Average</div>
<div class="stat-value">0.45</div>
<div class="progress-bar"><div class="progress-fill" style="width: 10%; background: var(--success);"></div></div>
</div>
</section>
<h2 style="font-size: 18px; margin-bottom: 20px; font-weight: 600;">Active Projects</h2>
<div class="dashboard-grid">
<div class="card">
<div class="card-header">
<div class="app-icon">
<svg viewBox="0 0 24 24" width="24" height="24"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
</div>
<div class="status-badge status-active">
<div style="width: 6px; height: 6px; background: currentColor; border-radius: 50%;"></div>
Running
</div>
</div>
<h3>juandenis.com</h3>
<a href="#" class="card-link">https://juandenis.com</a>
<div class="metric-row">
<div class="metric-item">
<span>Stack</span>
<span class="metric-value" style="color: #a78bfa;">WP / PHP 8.2</span>
</div>
<div class="metric-item">
<span>Uptime</span>
<span class="metric-value">14d 2h</span>
</div>
<div class="metric-item">
<button class="btn btn-secondary" style="padding: 4px 8px; font-size: 11px;">Manage</button>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<div class="app-icon">
<svg viewBox="0 0 24 24" width="24" height="24"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline></svg>
</div>
<div class="status-badge status-active">
<div style="width: 6px; height: 6px; background: currentColor; border-radius: 50%;"></div>
Running
</div>
</div>
<h3>api.samanlabs.com</h3>
<a href="#" class="card-link">https://api.samanlabs.com</a>
<div class="metric-row">
<div class="metric-item">
<span>Stack</span>
<span class="metric-value" style="color: #fcd34d;">Python / Flask</span>
</div>
<div class="metric-item">
<span>Port</span>
<span class="metric-value">8000</span>
</div>
<div class="metric-item">
<button class="btn btn-secondary" style="padding: 4px 8px; font-size: 11px;">Manage</button>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<div class="app-icon">
<svg viewBox="0 0 24 24" width="24" height="24"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"></path><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"></path></svg>
</div>
<div class="status-badge status-warning">
<div style="width: 6px; height: 6px; background: currentColor; border-radius: 50%;"></div>
Syncing
</div>
</div>
<h3>cecileblin.com</h3>
<a href="#" class="card-link">https://cecileblin.com</a>
<div class="metric-row">
<div class="metric-item">
<span>Stack</span>
<span class="metric-value" style="color: #60a5fa;">Static / HTML</span>
</div>
<div class="metric-item">
<span>Last Deploy</span>
<span class="metric-value">2m ago</span>
</div>
<div class="metric-item">
<button class="btn btn-secondary" style="padding: 4px 8px; font-size: 11px;">Manage</button>
</div>
</div>
</div>
</div>
</main>
</body>
</html>
+57
View File
@@ -0,0 +1,57 @@
# Project Intent
## Purpose
Provide project intent and behavioral expectations for Antigravity and Google models.
## Scope
Model neutral guidance. No permissions. No Claude specific instructions.
## One Paragraph Project Summary
This is a modern React dashboard application boilerplate built with Vite, featuring routing, charts, and a sidebar layout for building data-driven web interfaces.
## What the Project is For
To serve as a starting template for building React dashboard applications, providing essential setup for development, building, and deployment with components for navigation, data visualization, and user management.
## Stability Guarantees
- Uses stable versions of React, Vite, and related libraries
- Follows standard project structures for dashboards
- Includes routing and layout components
## Data Contracts and Invariants
- Components expect standard React props
- File structure adheres to src/ with App.jsx, main.jsx, components/, layouts/, pages/
- Uses react-router-dom for routing
- Charts use Recharts library
- Icons from Lucide React
## Compatibility Expectations
- Compatible with modern browsers and Node.js 16+
- Follows web standards
## Risk Tolerance Level
Low to medium - prefer proven libraries and avoid experimental features.
## What Changes are Considered Safe
- Adding new components, layouts, or pages
- Updating documentation
- Minor style adjustments
- Bug fixes in existing code
- Adding new routes
## What Changes Require Explicit Approval
- Major architectural changes
- Upgrading major dependencies
- Restructuring folders
- Introducing new charting libraries
- Removing existing routes or components
## Non Goals
- Not intended for server-side rendering
- Not a full-stack solution
- Avoids complex state management libraries by default
## Important Notes
Antigravity will also analyze README.md and other markdown documentation. This file clarifies intent, sets boundaries, and avoids duplicating documentation.
## Outcome
Antigravity builds a correct mental model of the project before acting.
+91
View File
@@ -0,0 +1,91 @@
# React Dashboard Template
A modern React dashboard application boilerplate built with Vite, featuring routing, charts, and a sidebar layout for building data-driven web interfaces.
## Features
- **React 18** with functional components and hooks
- **Vite** for fast development and building
- **React Router** for client-side routing
- **Recharts** for data visualization
- **Lucide React** for icons
- **ESLint** for code linting
- Responsive sidebar layout
- Dashboard page with sample components
## Getting Started
### Prerequisites
- Node.js 16+ and npm
### Installation
1. Clone or download this template
2. Install dependencies:
```bash
npm install
```
### Development
Start the development server:
```bash
npm run dev
```
The app will be available at `http://localhost:5173`.
### Building for Production
Build the app for deployment:
```bash
npm run build
```
The output will be in the `dist/` directory.
### Preview Production Build
```bash
npm run preview
```
## Project Structure
```
src/
├── App.jsx # Main app with routing
├── main.jsx # Entry point
├── index.css # Global styles
├── components/
│ └── Sidebar.jsx # Navigation sidebar
├── layouts/
│ └── DashboardLayout.jsx # Main layout wrapper
└── pages/
└── Dashboard.jsx # Main dashboard page
```
## Customization
- Modify components in `src/components/`
- Add new pages in `src/pages/`
- Update routes in `App.jsx`
- Customize styles in `index.css` or component files
## Environment Variables
Create a `.env` file in the root for environment variables:
```env
VITE_API_URL=https://api.example.com
```
Access them in code via `import.meta.env.VITE_API_URL`.
## Contributing
See the documentation files for AI agent permissions and guidelines.
+28
View File
@@ -0,0 +1,28 @@
# Agents Permissions
## Purpose
Establish strict permissions for any AI agent interacting with the repo.
## Scope
Safety and authorization only. No style or philosophy.
## Allowed Read and Write Paths
- `src/` (all files and subdirectories)
- `index.html`
- `package.json`
- `vite.config.js`
- `template.json`
- `how_it_works.md`
## Explicitly Forbidden Actions
- No file deletion
- No renaming public APIs
- No dependency upgrades
- No folder restructuring
- No shell execution unless explicitly requested
- Minimal diffs only
- JSON schemas are contracts
- Refactors require explicit approval
## Outcome
All agents know exactly what they can and cannot do before touching code.
+50
View File
@@ -0,0 +1,50 @@
# Claude Style Guide
## Purpose
Make Claude behave like a long-term contributor who already knows your preferences.
## Scope
Claude only. Style, structure, and expectations.
## How You Structure Code
- Use functional components with React hooks
- Separate logic into custom hooks when reusable
- Keep components small and focused
- Organize files in src/ with clear subdirectories (components/, layouts/, pages/)
## Naming Conventions
- PascalCase for component names (e.g., Sidebar.jsx)
- camelCase for variables, functions, and files (e.g., main.jsx)
- Descriptive names, avoid abbreviations
## Acceptable Abstractions
- Custom hooks for shared logic
- Context API for simple global state
- Utility functions in separate files
- Layout components for consistent structure
## What You Dislike
- Magic numbers or unexplained constants
- Over-engineering simple features
- Silent refactors without clear reasoning
- Deep nesting of components
## How You Want Diffs Scoped
- One logical change per commit
- Keep diffs minimal and focused
- Explain changes in commit messages
## How JSON Should be Shaped
- Use flat structures where possible
- Consistent key naming (camelCase)
- Avoid deeply nested objects
## What "Done" Means to You
- Code compiles and runs without errors
- Passes linting rules
- Implements the requested feature correctly
- Includes basic tests if applicable
- Documentation updated if needed
## Outcome
Claude outputs code that matches your thinking and style consistently.
+69
View File
@@ -0,0 +1,69 @@
# How It Works
This project was bootstrapped with a modern React boilerplate using **Vite**.
## 📂 Project Structure
```text
project_name/
├── index.html # Entry HTML file
├── package.json # Dependencies and scripts
├── vite.config.js # Vite configuration
└── src/
├── App.jsx # Main App component
├── main.jsx # Entry point
└── index.css # Global styles
```
## 🚀 Getting Started
### Installation
Install dependencies using npm:
```bash
npm install
```
### Development
Start the development server:
```bash
npm run dev
```
The app will be available at `http://localhost:5173`.
### Building for Production
Build the app for deployment:
```bash
npm run build
```
The output will be in the `dist/` directory.
## 🛠 Features
- **Vite**: Ultra-fast development server and bundler.
- **React**: Modern UI library.
- **ESLint**: Code linting.
- **Prettier**: Code formatting.
## 🔄 Customization
### Project Metadata
The project name and authors are automatically configured in `package.json` and generated files during initialization.
### Environment Variables
Create a `.env` file in the root for environment variables:
```env
VITE_API_URL=https://api.example.com
```
Access them in code via `import.meta.env.VITE_API_URL`.
+16
View File
@@ -0,0 +1,16 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>React Dashboard Template</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
+5093
View File
File diff suppressed because it is too large. Load diff
+30
View File
@@ -0,0 +1,30 @@
{
"name": "react-dashboard-template",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.22.3",
"recharts": "^2.12.3",
"lucide-react": "^0.363.0"
},
"devDependencies": {
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.1",
"eslint": "^9.9.0",
"eslint-plugin-react": "^7.35.0",
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
"eslint-plugin-react-refresh": "^0.4.9",
"globals": "^15.9.0",
"vite": "^5.4.1"
}
}
+20
View File
@@ -0,0 +1,20 @@
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import DashboardLayout from './layouts/DashboardLayout';
import Dashboard from './pages/Dashboard';
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<DashboardLayout />}>
<Route index element={<Dashboard />} />
<Route path="users" element={<div>Users Page</div>} />
<Route path="settings" element={<div>Settings Page</div>} />
</Route>
</Routes>
</Router>
);
}
export default App;
+27
View File
@@ -0,0 +1,27 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { LayoutDashboard, Users, Settings } from 'lucide-react';
const Sidebar = () => {
return (
<div className="sidebar">
<div className="sidebar-header">Admin</div>
<nav>
<Link to="/" className="nav-link">
<LayoutDashboard size={20} />
Dashboard
</Link>
<Link to="/users" className="nav-link">
<Users size={20} />
Users
</Link>
<Link to="/settings" className="nav-link">
<Settings size={20} />
Settings
</Link>
</nav>
</div>
);
};
export default Sidebar;
+93
View File
@@ -0,0 +1,93 @@
:root {
--primary-color: #3b82f6;
--bg-color: #f3f4f6;
--sidebar-width: 250px;
}
body {
margin: 0;
font-family: 'Inter', sans-serif;
background-color: var(--bg-color);
}
.dashboard-layout {
display: flex;
height: 100vh;
}
.sidebar {
width: var(--sidebar-width);
background-color: white;
border-right: 1px solid #e5e7eb;
padding: 20px;
display: flex;
flex-direction: column;
}
.sidebar-header {
font-size: 1.5rem;
font-weight: bold;
margin-bottom: 30px;
color: var(--primary-color);
}
.nav-link {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 15px;
color: #4b5563;
text-decoration: none;
border-radius: 6px;
margin-bottom: 5px;
transition: background-color 0.2s;
}
.nav-link:hover {
background-color: #eff6ff;
color: var(--primary-color);
}
.main-content {
flex: 1;
padding: 30px;
overflow-y: auto;
}
.header {
margin-bottom: 30px;
}
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.card {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.card h3 {
margin-top: 0;
color: #6b7280;
font-size: 0.9rem;
}
.card .value {
font-size: 1.8rem;
font-weight: bold;
color: #111827;
}
.chart-container {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
height: 400px;
}
+19
View File
@@ -0,0 +1,19 @@
import React from 'react';
import { Outlet } from 'react-router-dom';
import Sidebar from '../components/Sidebar';
const DashboardLayout = () => {
return (
<div className="dashboard-layout">
<Sidebar />
<main className="main-content">
<div className="header">
<h2>Dashboard</h2>
</div>
<Outlet />
</main>
</div>
);
};
export default DashboardLayout;
+10
View File
@@ -0,0 +1,10 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import './index.css'
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)
+48
View File
@@ -0,0 +1,48 @@
import React from 'react';
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';
const data = [
{ name: 'Jan', uv: 4000, pv: 2400, amt: 2400 },
{ name: 'Feb', uv: 3000, pv: 1398, amt: 2210 },
{ name: 'Mar', uv: 2000, pv: 9800, amt: 2290 },
{ name: 'Apr', uv: 2780, pv: 3908, amt: 2000 },
{ name: 'May', uv: 1890, pv: 4800, amt: 2181 },
{ name: 'Jun', uv: 2390, pv: 3800, amt: 2500 },
{ name: 'Jul', uv: 3490, pv: 4300, amt: 2100 },
];
const Dashboard = () => {
return (
<div>
<div className="card-grid">
<div className="card">
<h3>Total Users</h3>
<div className="value">1,234</div>
</div>
<div className="card">
<h3>Revenue</h3>
<div className="value">$45,678</div>
</div>
<div className="card">
<h3>Active Sessions</h3>
<div className="value">890</div>
</div>
</div>
<div className="chart-container">
<h3>Overview</h3>
<ResponsiveContainer width="100%" height="90%">
<BarChart data={data}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name" />
<YAxis />
<Tooltip />
<Bar dataKey="uv" fill="#3b82f6" />
</BarChart>
</ResponsiveContainer>
</div>
</div>
);
};
export default Dashboard;
+7
View File
@@ -0,0 +1,7 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
})