Spaces:
Sleeping
Sleeping
Delete Downloads/hackathon/civicai directory
Browse files- Downloads/hackathon/civicai/.env.example +0 -10
- Downloads/hackathon/civicai/.gitignore +0 -21
- Downloads/hackathon/civicai/README.md +0 -292
- Downloads/hackathon/civicai/lib/supabase.js +0 -6
- Downloads/hackathon/civicai/package-lock.json +0 -2130
- Downloads/hackathon/civicai/package.json +0 -28
- Downloads/hackathon/civicai/pages/_app.jsx +0 -4
- Downloads/hackathon/civicai/pages/api/alert.js +0 -56
- Downloads/hackathon/civicai/pages/api/process.js +0 -530
- Downloads/hackathon/civicai/pages/api/status.js +0 -14
- Downloads/hackathon/civicai/pages/api/transcribe.js +0 -69
- Downloads/hackathon/civicai/pages/dashboard.jsx +0 -405
- Downloads/hackathon/civicai/pages/index.jsx +0 -568
- Downloads/hackathon/civicai/pages/login.jsx +0 -108
- Downloads/hackathon/civicai/pages/support.jsx +0 -101
- Downloads/hackathon/civicai/postcss.config.js +0 -1
- Downloads/hackathon/civicai/styles/globals.css +0 -34
- Downloads/hackathon/civicai/tailwind.config.js +0 -35
Downloads/hackathon/civicai/.env.example
DELETED
|
@@ -1,10 +0,0 @@
|
|
| 1 |
-
# Copy this file to .env.local and fill in real values (do NOT commit .env.local)
|
| 2 |
-
|
| 3 |
-
ANTHROPIC_API_KEY=sk-your-anthropic-key-here
|
| 4 |
-
OPENAI_API_KEY=sk-your-openai-key-here
|
| 5 |
-
NEXT_PUBLIC_SUPABASE_URL=https://your-supabase-url.supabase.co
|
| 6 |
-
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-supabase-anon-key-here
|
| 7 |
-
SENDGRID_API_KEY=SG.your-sendgrid-key-here
|
| 8 |
-
ALERT_EMAIL=authority@yourcity.gov.in
|
| 9 |
-
LOCATIONIQ_KEY=pk.your-locationiq-key-here
|
| 10 |
-
NEXT_PUBLIC_BASE_URL=http://localhost:3000
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Downloads/hackathon/civicai/.gitignore
DELETED
|
@@ -1,21 +0,0 @@
|
|
| 1 |
-
# Dependencies
|
| 2 |
-
node_modules/
|
| 3 |
-
.pnp
|
| 4 |
-
.pnp.js
|
| 5 |
-
|
| 6 |
-
# Environment variables — NEVER commit these
|
| 7 |
-
.env.local
|
| 8 |
-
.env.development.local
|
| 9 |
-
.env.test.local
|
| 10 |
-
.env.production.local
|
| 11 |
-
|
| 12 |
-
# Next.js build output
|
| 13 |
-
.next/
|
| 14 |
-
out/
|
| 15 |
-
|
| 16 |
-
# Misc
|
| 17 |
-
.DS_Store
|
| 18 |
-
*.pem
|
| 19 |
-
npm-debug.log*
|
| 20 |
-
yarn-debug.log*
|
| 21 |
-
yarn-error.log*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Downloads/hackathon/civicai/README.md
DELETED
|
@@ -1,292 +0,0 @@
|
|
| 1 |
-
# CitizenCare 🏛️
|
| 2 |
-
|
| 3 |
-
An intelligent AI-powered citizen grievance classification and tracking portal that enables seamless complaint submission, real-time status tracking, and efficient authority dashboard management.
|
| 4 |
-
|
| 5 |
-
## 🎯 Features
|
| 6 |
-
|
| 7 |
-
- **Multi-Language Support**: Submit complaints in 10 Indian languages (English, Hindi, Telugu, Tamil, Kannada, Marathi, Bengali, Gujarati, Punjabi, Odia)
|
| 8 |
-
- **Voice & Text Input**: Record complaints directly or type them in
|
| 9 |
-
- **Smart Classification**: AI-powered keyword parser automatically categorizes complaints and assigns departments
|
| 10 |
-
- **Urgency Detection**: System intelligently identifies critical issues and triggers instant alerts
|
| 11 |
-
- **Real-Time Tracking**: Citizens can track complaint status with unique complaint IDs
|
| 12 |
-
- **Authority Dashboard**: Comprehensive dashboard for government officials to manage and resolve complaints
|
| 13 |
-
- **Visual Analytics**: Charts and filters to analyze complaint patterns by department and urgency
|
| 14 |
-
- **Secure Authentication**: Role-based access control with Supabase Auth
|
| 15 |
-
- **Responsive Design**: Beautiful, mobile-friendly UI with vibrant color scheme
|
| 16 |
-
|
| 17 |
-
## 🛠️ Tech Stack
|
| 18 |
-
|
| 19 |
-
- **Frontend**: Next.js, React, Tailwind CSS
|
| 20 |
-
- **Backend**: Next.js API Routes
|
| 21 |
-
- **Database**: Supabase (PostgreSQL) with real-time subscriptions
|
| 22 |
-
- **Authentication**: Supabase Auth
|
| 23 |
-
- **Voice Recognition**: Browser Web Speech API + OpenAI Whisper fallback
|
| 24 |
-
- **Email Alerts**: SendGrid (for critical complaints)
|
| 25 |
-
- **Charts**: Chart.js + react-chartjs-2
|
| 26 |
-
- **Hosting**: Vercel (recommended)
|
| 27 |
-
|
| 28 |
-
## 📋 System Architecture
|
| 29 |
-
|
| 30 |
-
```
|
| 31 |
-
┌─────────────────┐
|
| 32 |
-
│ Citizen Portal │ (index.jsx, support.jsx)
|
| 33 |
-
├─────────────────┤
|
| 34 |
-
│ Voice/Text │
|
| 35 |
-
│ Input Handler │
|
| 36 |
-
└────────┬────────┘
|
| 37 |
-
│
|
| 38 |
-
▼
|
| 39 |
-
┌─────────────────┐
|
| 40 |
-
│ API Processor │ (api/process.js)
|
| 41 |
-
│ - Keywords │
|
| 42 |
-
│ - Scoring │
|
| 43 |
-
│ - Department │
|
| 44 |
-
│ - Urgency │
|
| 45 |
-
└────────┬────────┘
|
| 46 |
-
│
|
| 47 |
-
▼
|
| 48 |
-
┌─────────────────┐
|
| 49 |
-
│ Database │ (Supabase)
|
| 50 |
-
│ - Store │
|
| 51 |
-
│ - Realtime │
|
| 52 |
-
└────────┬────────┘
|
| 53 |
-
│
|
| 54 |
-
▼
|
| 55 |
-
┌─────────────────┐
|
| 56 |
-
│ Authority │ (dashboard.jsx)
|
| 57 |
-
│ Dashboard │
|
| 58 |
-
│ - View │
|
| 59 |
-
│ - Filter │
|
| 60 |
-
│ - Update │
|
| 61 |
-
└─────────────────┘
|
| 62 |
-
```
|
| 63 |
-
|
| 64 |
-
## 🚀 Getting Started
|
| 65 |
-
|
| 66 |
-
### Prerequisites
|
| 67 |
-
- Node.js 16+ and npm
|
| 68 |
-
- Supabase account
|
| 69 |
-
- SendGrid account (for alerts)
|
| 70 |
-
- Git
|
| 71 |
-
|
| 72 |
-
### Installation
|
| 73 |
-
|
| 74 |
-
1. **Clone the repository**
|
| 75 |
-
```bash
|
| 76 |
-
git clone https://github.com/SAI-RAHUL-ROKKAM/CitizenCare.git
|
| 77 |
-
cd CitizenCare
|
| 78 |
-
```
|
| 79 |
-
|
| 80 |
-
2. **Install dependencies**
|
| 81 |
-
```bash
|
| 82 |
-
npm install
|
| 83 |
-
```
|
| 84 |
-
|
| 85 |
-
3. **Create environment file**
|
| 86 |
-
```bash
|
| 87 |
-
cp .env.example .env.local
|
| 88 |
-
```
|
| 89 |
-
|
| 90 |
-
4. **Fill in your environment variables in `.env.local`**
|
| 91 |
-
```
|
| 92 |
-
ANTHROPIC_API_KEY=your_key_here
|
| 93 |
-
OPENAI_API_KEY=your_key_here
|
| 94 |
-
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
|
| 95 |
-
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_key
|
| 96 |
-
SENDGRID_API_KEY=your_sendgrid_key
|
| 97 |
-
ALERT_EMAIL=authority@yourcity.gov.in
|
| 98 |
-
LOCATIONIQ_KEY=your_locationiq_key
|
| 99 |
-
NEXT_PUBLIC_BASE_URL=http://localhost:3000
|
| 100 |
-
```
|
| 101 |
-
|
| 102 |
-
5. **Run the development server**
|
| 103 |
-
```bash
|
| 104 |
-
npm run dev
|
| 105 |
-
```
|
| 106 |
-
|
| 107 |
-
6. **Open in browser**
|
| 108 |
-
```
|
| 109 |
-
http://localhost:3000
|
| 110 |
-
```
|
| 111 |
-
|
| 112 |
-
## 📱 Usage
|
| 113 |
-
|
| 114 |
-
### For Citizens
|
| 115 |
-
1. Visit `http://localhost:3000`
|
| 116 |
-
2. Type or record a complaint in any supported language
|
| 117 |
-
3. Click "Submit complaint"
|
| 118 |
-
4. View generated complaint summary, department, and urgency
|
| 119 |
-
5. Copy complaint ID to track status
|
| 120 |
-
6. Use "Track complaint" tab to check real-time updates
|
| 121 |
-
|
| 122 |
-
### For Authorities
|
| 123 |
-
1. Visit `http://localhost:3000/login`
|
| 124 |
-
2. Sign up or use test credentials:
|
| 125 |
-
- Email: `authority-test@citizencare.test`
|
| 126 |
-
- Password: `Test@1234`
|
| 127 |
-
3. View dashboard with:
|
| 128 |
-
- Statistics (total, pending, resolved, critical)
|
| 129 |
-
- Charts by department and urgency
|
| 130 |
-
- Complaint list with filters
|
| 131 |
-
- Click any complaint to view details and update status
|
| 132 |
-
|
| 133 |
-
## 🔐 Security
|
| 134 |
-
|
| 135 |
-
- ✅ Environment variables protected in `.env.local` (excluded from Git)
|
| 136 |
-
- ✅ `.env.example` contains only dummy keys
|
| 137 |
-
- ✅ Supabase Row Level Security (RLS) for database access control
|
| 138 |
-
- ✅ Role-based authentication for authority dashboard
|
| 139 |
-
- ✅ No API keys exposed in source code
|
| 140 |
-
- ✅ SendGrid alerts only for critical complaints
|
| 141 |
-
|
| 142 |
-
## 📁 Project Structure
|
| 143 |
-
|
| 144 |
-
```
|
| 145 |
-
CitizenCare/
|
| 146 |
-
├── pages/
|
| 147 |
-
│ ├── _app.jsx # App wrapper
|
| 148 |
-
│ ├── index.jsx # Citizen portal (submit/track)
|
| 149 |
-
│ ├── dashboard.jsx # Authority dashboard
|
| 150 |
-
│ ├── login.jsx # Authentication
|
| 151 |
-
│ ├── support.jsx # FAQ & help center
|
| 152 |
-
│ └── api/
|
| 153 |
-
│ ├── process.js # Complaint parser & classifier
|
| 154 |
-
│ ├── status.js # Track complaint status
|
| 155 |
-
│ ├── alert.js # Send critical alerts
|
| 156 |
-
│ └── transcribe.js # Voice transcription
|
| 157 |
-
├── lib/
|
| 158 |
-
│ └── supabase.js # Supabase client config
|
| 159 |
-
├── styles/
|
| 160 |
-
│ └── globals.css # Global styles & animations
|
| 161 |
-
├── .env.example # Environment template
|
| 162 |
-
├── .gitignore # Git ignore rules
|
| 163 |
-
├── package.json # Dependencies
|
| 164 |
-
├── tailwind.config.js # Tailwind configuration
|
| 165 |
-
└── postcss.config.js # PostCSS configuration
|
| 166 |
-
```
|
| 167 |
-
|
| 168 |
-
## 🧠 How It Works
|
| 169 |
-
|
| 170 |
-
### Complaint Processing Flow
|
| 171 |
-
|
| 172 |
-
1. **Input**: Citizen submits text/voice in any language
|
| 173 |
-
2. **Detection**: System detects language from Unicode script
|
| 174 |
-
3. **Scoring**: Multi-keyword scoring system finds best department match
|
| 175 |
-
4. **Rules**: Override rules for critical medical/safety terms
|
| 176 |
-
5. **Extraction**: Location parsing using regex patterns
|
| 177 |
-
6. **Classification**: Department, urgency, and action items assigned
|
| 178 |
-
7. **Storage**: Complaint saved to Supabase with `status: pending`
|
| 179 |
-
8. **Alerts**: If critical → SendGrid email sent to authority
|
| 180 |
-
9. **Tracking**: Citizen gets unique ID to track status
|
| 181 |
-
|
| 182 |
-
### Department Keywords
|
| 183 |
-
|
| 184 |
-
System supports keywords in 10 languages for:
|
| 185 |
-
- Health, Hospital
|
| 186 |
-
- Police
|
| 187 |
-
- Sanitation
|
| 188 |
-
- Roads, Water, Electricity
|
| 189 |
-
- Education
|
| 190 |
-
- Transport
|
| 191 |
-
- Municipal
|
| 192 |
-
- Environment
|
| 193 |
-
- Rescue
|
| 194 |
-
- Other (fallback)
|
| 195 |
-
|
| 196 |
-
## 🎓 Example Test Cases
|
| 197 |
-
|
| 198 |
-
### Test 1: Health Emergency ✅
|
| 199 |
-
**Input**: "my teacher got a heart attack our school is at lalitha nagar , rajahmundry"
|
| 200 |
-
**Result**:
|
| 201 |
-
- Department: Health
|
| 202 |
-
- Urgency: Critical
|
| 203 |
-
- ETA: 12 hours
|
| 204 |
-
|
| 205 |
-
### Test 2: Road Issue ✅
|
| 206 |
-
**Input**: "large pothole near Ramaiah School on MG Road. Two bikes fell last week"
|
| 207 |
-
**Result**:
|
| 208 |
-
- Department: Roads
|
| 209 |
-
- Urgency: High
|
| 210 |
-
- ETA: 24-48 hours
|
| 211 |
-
|
| 212 |
-
### Test 3: Sanitation ✅
|
| 213 |
-
**Input**: "गंदगी और कचरे के ढेर हमारे इलाके में"
|
| 214 |
-
**Result**:
|
| 215 |
-
- Department: Sanitation
|
| 216 |
-
- Urgency: Medium
|
| 217 |
-
- ETA: 3-5 days
|
| 218 |
-
|
| 219 |
-
## 🚀 Deployment
|
| 220 |
-
|
| 221 |
-
### Deploy to Vercel (Recommended)
|
| 222 |
-
|
| 223 |
-
1. Push code to GitHub
|
| 224 |
-
2. Connect repo to Vercel
|
| 225 |
-
3. Add environment variables in Vercel dashboard
|
| 226 |
-
4. Deploy automatically on push
|
| 227 |
-
|
| 228 |
-
```bash
|
| 229 |
-
git push origin main
|
| 230 |
-
# Vercel auto-deploys
|
| 231 |
-
```
|
| 232 |
-
|
| 233 |
-
### Environment Variables for Production
|
| 234 |
-
Set these in your hosting platform (Vercel, Netlify, etc.):
|
| 235 |
-
- `ANTHROPIC_API_KEY`
|
| 236 |
-
- `OPENAI_API_KEY`
|
| 237 |
-
- `NEXT_PUBLIC_SUPABASE_URL`
|
| 238 |
-
- `NEXT_PUBLIC_SUPABASE_ANON_KEY`
|
| 239 |
-
- `SENDGRID_API_KEY`
|
| 240 |
-
- `ALERT_EMAIL`
|
| 241 |
-
- `LOCATIONIQ_KEY`
|
| 242 |
-
- `NEXT_PUBLIC_BASE_URL` (your domain)
|
| 243 |
-
|
| 244 |
-
## 📊 Performance
|
| 245 |
-
|
| 246 |
-
- **Processing Time**: < 3 seconds for complaint classification
|
| 247 |
-
- **Database**: Real-time sync using Supabase subscriptions
|
| 248 |
-
- **Voice Input**: Supports 10 languages with offline fallback
|
| 249 |
-
- **Responsive**: Mobile, tablet, and desktop optimized
|
| 250 |
-
|
| 251 |
-
## 🔮 Future Enhancements
|
| 252 |
-
|
| 253 |
-
- [ ] ML/NLP model for intent classification
|
| 254 |
-
- [ ] Map-based geo-visualization of complaints
|
| 255 |
-
- [ ] SMS/WhatsApp citizen notifications
|
| 256 |
-
- [ ] Advanced admin dashboard with SLA tracking
|
| 257 |
-
- [ ] Automated translation to English
|
| 258 |
-
- [ ] Chat support interface
|
| 259 |
-
- [ ] Gamification (badges/credits for citizens)
|
| 260 |
-
- [ ] Photo/video attachments
|
| 261 |
-
- [ ] Integration with government databases
|
| 262 |
-
- [ ] Analytics and reporting tools
|
| 263 |
-
|
| 264 |
-
## 🤝 Contributing
|
| 265 |
-
|
| 266 |
-
Contributions are welcome! Please:
|
| 267 |
-
1. Fork the repository
|
| 268 |
-
2. Create a feature branch (`git checkout -b feature/AmazingFeature`)
|
| 269 |
-
3. Commit changes (`git commit -m 'Add AmazingFeature'`)
|
| 270 |
-
4. Push to branch (`git push origin feature/AmazingFeature`)
|
| 271 |
-
5. Open a Pull Request
|
| 272 |
-
|
| 273 |
-
## 📝 License
|
| 274 |
-
|
| 275 |
-
This project is open source and available under the MIT License.
|
| 276 |
-
|
| 277 |
-
## 📞 Support
|
| 278 |
-
|
| 279 |
-
For issues or questions:
|
| 280 |
-
- Create an issue on GitHub
|
| 281 |
-
- Check the FAQ in `/support` page
|
| 282 |
-
- Visit help center at `http://localhost:3000/support`
|
| 283 |
-
|
| 284 |
-
## 👨💻 Authors
|
| 285 |
-
|
| 286 |
-
- **SAI RAHUL ROKKAM** - Initial development
|
| 287 |
-
|
| 288 |
-
Built for the National Hackathon 2026
|
| 289 |
-
|
| 290 |
-
---
|
| 291 |
-
|
| 292 |
-
**Made with ❤️ for better citizen-government communication**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Downloads/hackathon/civicai/lib/supabase.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
| 1 |
-
import { createClient } from '@supabase/supabase-js'
|
| 2 |
-
|
| 3 |
-
export const supabase = createClient(
|
| 4 |
-
process.env.NEXT_PUBLIC_SUPABASE_URL,
|
| 5 |
-
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
|
| 6 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Downloads/hackathon/civicai/package-lock.json
DELETED
|
@@ -1,2130 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"name": "civicai",
|
| 3 |
-
"version": "0.1.0",
|
| 4 |
-
"lockfileVersion": 3,
|
| 5 |
-
"requires": true,
|
| 6 |
-
"packages": {
|
| 7 |
-
"": {
|
| 8 |
-
"name": "civicai",
|
| 9 |
-
"version": "0.1.0",
|
| 10 |
-
"dependencies": {
|
| 11 |
-
"@sendgrid/mail": "^8.1.6",
|
| 12 |
-
"@supabase/supabase-js": "^2.100.1",
|
| 13 |
-
"chart.js": "^4.5.1",
|
| 14 |
-
"form-data": "^4.0.0",
|
| 15 |
-
"formidable": "^3.5.1",
|
| 16 |
-
"git": "^0.1.5",
|
| 17 |
-
"next": "^14.0.0",
|
| 18 |
-
"react": "^18.0.0",
|
| 19 |
-
"react-chartjs-2": "^5.3.1",
|
| 20 |
-
"react-dom": "^18.0.0",
|
| 21 |
-
"uuid": "^9.0.1"
|
| 22 |
-
},
|
| 23 |
-
"devDependencies": {
|
| 24 |
-
"autoprefixer": "^10.4.16",
|
| 25 |
-
"postcss": "^8.4.32",
|
| 26 |
-
"tailwindcss": "^3.4.0"
|
| 27 |
-
}
|
| 28 |
-
},
|
| 29 |
-
"node_modules/@alloc/quick-lru": {
|
| 30 |
-
"version": "5.2.0",
|
| 31 |
-
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
|
| 32 |
-
"integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
|
| 33 |
-
"dev": true,
|
| 34 |
-
"license": "MIT",
|
| 35 |
-
"engines": {
|
| 36 |
-
"node": ">=10"
|
| 37 |
-
},
|
| 38 |
-
"funding": {
|
| 39 |
-
"url": "https://github.com/sponsors/sindresorhus"
|
| 40 |
-
}
|
| 41 |
-
},
|
| 42 |
-
"node_modules/@jridgewell/gen-mapping": {
|
| 43 |
-
"version": "0.3.13",
|
| 44 |
-
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
|
| 45 |
-
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
|
| 46 |
-
"dev": true,
|
| 47 |
-
"license": "MIT",
|
| 48 |
-
"dependencies": {
|
| 49 |
-
"@jridgewell/sourcemap-codec": "^1.5.0",
|
| 50 |
-
"@jridgewell/trace-mapping": "^0.3.24"
|
| 51 |
-
}
|
| 52 |
-
},
|
| 53 |
-
"node_modules/@jridgewell/resolve-uri": {
|
| 54 |
-
"version": "3.1.2",
|
| 55 |
-
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
| 56 |
-
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
| 57 |
-
"dev": true,
|
| 58 |
-
"license": "MIT",
|
| 59 |
-
"engines": {
|
| 60 |
-
"node": ">=6.0.0"
|
| 61 |
-
}
|
| 62 |
-
},
|
| 63 |
-
"node_modules/@jridgewell/sourcemap-codec": {
|
| 64 |
-
"version": "1.5.5",
|
| 65 |
-
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
|
| 66 |
-
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
|
| 67 |
-
"dev": true,
|
| 68 |
-
"license": "MIT"
|
| 69 |
-
},
|
| 70 |
-
"node_modules/@jridgewell/trace-mapping": {
|
| 71 |
-
"version": "0.3.31",
|
| 72 |
-
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
|
| 73 |
-
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
|
| 74 |
-
"dev": true,
|
| 75 |
-
"license": "MIT",
|
| 76 |
-
"dependencies": {
|
| 77 |
-
"@jridgewell/resolve-uri": "^3.1.0",
|
| 78 |
-
"@jridgewell/sourcemap-codec": "^1.4.14"
|
| 79 |
-
}
|
| 80 |
-
},
|
| 81 |
-
"node_modules/@kurkle/color": {
|
| 82 |
-
"version": "0.3.4",
|
| 83 |
-
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz",
|
| 84 |
-
"integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==",
|
| 85 |
-
"license": "MIT"
|
| 86 |
-
},
|
| 87 |
-
"node_modules/@next/env": {
|
| 88 |
-
"version": "14.2.35",
|
| 89 |
-
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.35.tgz",
|
| 90 |
-
"integrity": "sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==",
|
| 91 |
-
"license": "MIT"
|
| 92 |
-
},
|
| 93 |
-
"node_modules/@next/swc-darwin-arm64": {
|
| 94 |
-
"version": "14.2.33",
|
| 95 |
-
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.33.tgz",
|
| 96 |
-
"integrity": "sha512-HqYnb6pxlsshoSTubdXKu15g3iivcbsMXg4bYpjL2iS/V6aQot+iyF4BUc2qA/J/n55YtvE4PHMKWBKGCF/+wA==",
|
| 97 |
-
"cpu": [
|
| 98 |
-
"arm64"
|
| 99 |
-
],
|
| 100 |
-
"license": "MIT",
|
| 101 |
-
"optional": true,
|
| 102 |
-
"os": [
|
| 103 |
-
"darwin"
|
| 104 |
-
],
|
| 105 |
-
"engines": {
|
| 106 |
-
"node": ">= 10"
|
| 107 |
-
}
|
| 108 |
-
},
|
| 109 |
-
"node_modules/@next/swc-darwin-x64": {
|
| 110 |
-
"version": "14.2.33",
|
| 111 |
-
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.33.tgz",
|
| 112 |
-
"integrity": "sha512-8HGBeAE5rX3jzKvF593XTTFg3gxeU4f+UWnswa6JPhzaR6+zblO5+fjltJWIZc4aUalqTclvN2QtTC37LxvZAA==",
|
| 113 |
-
"cpu": [
|
| 114 |
-
"x64"
|
| 115 |
-
],
|
| 116 |
-
"license": "MIT",
|
| 117 |
-
"optional": true,
|
| 118 |
-
"os": [
|
| 119 |
-
"darwin"
|
| 120 |
-
],
|
| 121 |
-
"engines": {
|
| 122 |
-
"node": ">= 10"
|
| 123 |
-
}
|
| 124 |
-
},
|
| 125 |
-
"node_modules/@next/swc-linux-arm64-gnu": {
|
| 126 |
-
"version": "14.2.33",
|
| 127 |
-
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.33.tgz",
|
| 128 |
-
"integrity": "sha512-JXMBka6lNNmqbkvcTtaX8Gu5by9547bukHQvPoLe9VRBx1gHwzf5tdt4AaezW85HAB3pikcvyqBToRTDA4DeLw==",
|
| 129 |
-
"cpu": [
|
| 130 |
-
"arm64"
|
| 131 |
-
],
|
| 132 |
-
"license": "MIT",
|
| 133 |
-
"optional": true,
|
| 134 |
-
"os": [
|
| 135 |
-
"linux"
|
| 136 |
-
],
|
| 137 |
-
"engines": {
|
| 138 |
-
"node": ">= 10"
|
| 139 |
-
}
|
| 140 |
-
},
|
| 141 |
-
"node_modules/@next/swc-linux-arm64-musl": {
|
| 142 |
-
"version": "14.2.33",
|
| 143 |
-
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.33.tgz",
|
| 144 |
-
"integrity": "sha512-Bm+QulsAItD/x6Ih8wGIMfRJy4G73tu1HJsrccPW6AfqdZd0Sfm5Imhgkgq2+kly065rYMnCOxTBvmvFY1BKfg==",
|
| 145 |
-
"cpu": [
|
| 146 |
-
"arm64"
|
| 147 |
-
],
|
| 148 |
-
"license": "MIT",
|
| 149 |
-
"optional": true,
|
| 150 |
-
"os": [
|
| 151 |
-
"linux"
|
| 152 |
-
],
|
| 153 |
-
"engines": {
|
| 154 |
-
"node": ">= 10"
|
| 155 |
-
}
|
| 156 |
-
},
|
| 157 |
-
"node_modules/@next/swc-linux-x64-gnu": {
|
| 158 |
-
"version": "14.2.33",
|
| 159 |
-
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.33.tgz",
|
| 160 |
-
"integrity": "sha512-FnFn+ZBgsVMbGDsTqo8zsnRzydvsGV8vfiWwUo1LD8FTmPTdV+otGSWKc4LJec0oSexFnCYVO4hX8P8qQKaSlg==",
|
| 161 |
-
"cpu": [
|
| 162 |
-
"x64"
|
| 163 |
-
],
|
| 164 |
-
"license": "MIT",
|
| 165 |
-
"optional": true,
|
| 166 |
-
"os": [
|
| 167 |
-
"linux"
|
| 168 |
-
],
|
| 169 |
-
"engines": {
|
| 170 |
-
"node": ">= 10"
|
| 171 |
-
}
|
| 172 |
-
},
|
| 173 |
-
"node_modules/@next/swc-linux-x64-musl": {
|
| 174 |
-
"version": "14.2.33",
|
| 175 |
-
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.33.tgz",
|
| 176 |
-
"integrity": "sha512-345tsIWMzoXaQndUTDv1qypDRiebFxGYx9pYkhwY4hBRaOLt8UGfiWKr9FSSHs25dFIf8ZqIFaPdy5MljdoawA==",
|
| 177 |
-
"cpu": [
|
| 178 |
-
"x64"
|
| 179 |
-
],
|
| 180 |
-
"license": "MIT",
|
| 181 |
-
"optional": true,
|
| 182 |
-
"os": [
|
| 183 |
-
"linux"
|
| 184 |
-
],
|
| 185 |
-
"engines": {
|
| 186 |
-
"node": ">= 10"
|
| 187 |
-
}
|
| 188 |
-
},
|
| 189 |
-
"node_modules/@next/swc-win32-arm64-msvc": {
|
| 190 |
-
"version": "14.2.33",
|
| 191 |
-
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.33.tgz",
|
| 192 |
-
"integrity": "sha512-nscpt0G6UCTkrT2ppnJnFsYbPDQwmum4GNXYTeoTIdsmMydSKFz9Iny2jpaRupTb+Wl298+Rh82WKzt9LCcqSQ==",
|
| 193 |
-
"cpu": [
|
| 194 |
-
"arm64"
|
| 195 |
-
],
|
| 196 |
-
"license": "MIT",
|
| 197 |
-
"optional": true,
|
| 198 |
-
"os": [
|
| 199 |
-
"win32"
|
| 200 |
-
],
|
| 201 |
-
"engines": {
|
| 202 |
-
"node": ">= 10"
|
| 203 |
-
}
|
| 204 |
-
},
|
| 205 |
-
"node_modules/@next/swc-win32-ia32-msvc": {
|
| 206 |
-
"version": "14.2.33",
|
| 207 |
-
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.33.tgz",
|
| 208 |
-
"integrity": "sha512-pc9LpGNKhJ0dXQhZ5QMmYxtARwwmWLpeocFmVG5Z0DzWq5Uf0izcI8tLc+qOpqxO1PWqZ5A7J1blrUIKrIFc7Q==",
|
| 209 |
-
"cpu": [
|
| 210 |
-
"ia32"
|
| 211 |
-
],
|
| 212 |
-
"license": "MIT",
|
| 213 |
-
"optional": true,
|
| 214 |
-
"os": [
|
| 215 |
-
"win32"
|
| 216 |
-
],
|
| 217 |
-
"engines": {
|
| 218 |
-
"node": ">= 10"
|
| 219 |
-
}
|
| 220 |
-
},
|
| 221 |
-
"node_modules/@next/swc-win32-x64-msvc": {
|
| 222 |
-
"version": "14.2.33",
|
| 223 |
-
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.33.tgz",
|
| 224 |
-
"integrity": "sha512-nOjfZMy8B94MdisuzZo9/57xuFVLHJaDj5e/xrduJp9CV2/HrfxTRH2fbyLe+K9QT41WBLUd4iXX3R7jBp0EUg==",
|
| 225 |
-
"cpu": [
|
| 226 |
-
"x64"
|
| 227 |
-
],
|
| 228 |
-
"license": "MIT",
|
| 229 |
-
"optional": true,
|
| 230 |
-
"os": [
|
| 231 |
-
"win32"
|
| 232 |
-
],
|
| 233 |
-
"engines": {
|
| 234 |
-
"node": ">= 10"
|
| 235 |
-
}
|
| 236 |
-
},
|
| 237 |
-
"node_modules/@noble/hashes": {
|
| 238 |
-
"version": "1.8.0",
|
| 239 |
-
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
|
| 240 |
-
"integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
|
| 241 |
-
"license": "MIT",
|
| 242 |
-
"engines": {
|
| 243 |
-
"node": "^14.21.3 || >=16"
|
| 244 |
-
},
|
| 245 |
-
"funding": {
|
| 246 |
-
"url": "https://paulmillr.com/funding/"
|
| 247 |
-
}
|
| 248 |
-
},
|
| 249 |
-
"node_modules/@nodelib/fs.scandir": {
|
| 250 |
-
"version": "2.1.5",
|
| 251 |
-
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
| 252 |
-
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
|
| 253 |
-
"dev": true,
|
| 254 |
-
"license": "MIT",
|
| 255 |
-
"dependencies": {
|
| 256 |
-
"@nodelib/fs.stat": "2.0.5",
|
| 257 |
-
"run-parallel": "^1.1.9"
|
| 258 |
-
},
|
| 259 |
-
"engines": {
|
| 260 |
-
"node": ">= 8"
|
| 261 |
-
}
|
| 262 |
-
},
|
| 263 |
-
"node_modules/@nodelib/fs.stat": {
|
| 264 |
-
"version": "2.0.5",
|
| 265 |
-
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
|
| 266 |
-
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
|
| 267 |
-
"dev": true,
|
| 268 |
-
"license": "MIT",
|
| 269 |
-
"engines": {
|
| 270 |
-
"node": ">= 8"
|
| 271 |
-
}
|
| 272 |
-
},
|
| 273 |
-
"node_modules/@nodelib/fs.walk": {
|
| 274 |
-
"version": "1.2.8",
|
| 275 |
-
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
|
| 276 |
-
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
|
| 277 |
-
"dev": true,
|
| 278 |
-
"license": "MIT",
|
| 279 |
-
"dependencies": {
|
| 280 |
-
"@nodelib/fs.scandir": "2.1.5",
|
| 281 |
-
"fastq": "^1.6.0"
|
| 282 |
-
},
|
| 283 |
-
"engines": {
|
| 284 |
-
"node": ">= 8"
|
| 285 |
-
}
|
| 286 |
-
},
|
| 287 |
-
"node_modules/@paralleldrive/cuid2": {
|
| 288 |
-
"version": "2.3.1",
|
| 289 |
-
"resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz",
|
| 290 |
-
"integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==",
|
| 291 |
-
"license": "MIT",
|
| 292 |
-
"dependencies": {
|
| 293 |
-
"@noble/hashes": "^1.1.5"
|
| 294 |
-
}
|
| 295 |
-
},
|
| 296 |
-
"node_modules/@sendgrid/client": {
|
| 297 |
-
"version": "8.1.6",
|
| 298 |
-
"resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-8.1.6.tgz",
|
| 299 |
-
"integrity": "sha512-/BHu0hqwXNHr2aLhcXU7RmmlVqrdfrbY9KpaNj00KZHlVOVoRxRVrpOCabIB+91ISXJ6+mLM9vpaVUhK6TwBWA==",
|
| 300 |
-
"license": "MIT",
|
| 301 |
-
"dependencies": {
|
| 302 |
-
"@sendgrid/helpers": "^8.0.0",
|
| 303 |
-
"axios": "^1.12.0"
|
| 304 |
-
},
|
| 305 |
-
"engines": {
|
| 306 |
-
"node": ">=12.*"
|
| 307 |
-
}
|
| 308 |
-
},
|
| 309 |
-
"node_modules/@sendgrid/helpers": {
|
| 310 |
-
"version": "8.0.0",
|
| 311 |
-
"resolved": "https://registry.npmjs.org/@sendgrid/helpers/-/helpers-8.0.0.tgz",
|
| 312 |
-
"integrity": "sha512-Ze7WuW2Xzy5GT5WRx+yEv89fsg/pgy3T1E3FS0QEx0/VvRmigMZ5qyVGhJz4SxomegDkzXv/i0aFPpHKN8qdAA==",
|
| 313 |
-
"license": "MIT",
|
| 314 |
-
"dependencies": {
|
| 315 |
-
"deepmerge": "^4.2.2"
|
| 316 |
-
},
|
| 317 |
-
"engines": {
|
| 318 |
-
"node": ">= 12.0.0"
|
| 319 |
-
}
|
| 320 |
-
},
|
| 321 |
-
"node_modules/@sendgrid/mail": {
|
| 322 |
-
"version": "8.1.6",
|
| 323 |
-
"resolved": "https://registry.npmjs.org/@sendgrid/mail/-/mail-8.1.6.tgz",
|
| 324 |
-
"integrity": "sha512-/ZqxUvKeEztU9drOoPC/8opEPOk+jLlB2q4+xpx6HVLq6aFu3pMpalkTpAQz8XfRfpLp8O25bh6pGPcHDCYpqg==",
|
| 325 |
-
"license": "MIT",
|
| 326 |
-
"dependencies": {
|
| 327 |
-
"@sendgrid/client": "^8.1.5",
|
| 328 |
-
"@sendgrid/helpers": "^8.0.0"
|
| 329 |
-
},
|
| 330 |
-
"engines": {
|
| 331 |
-
"node": ">=12.*"
|
| 332 |
-
}
|
| 333 |
-
},
|
| 334 |
-
"node_modules/@supabase/auth-js": {
|
| 335 |
-
"version": "2.100.1",
|
| 336 |
-
"resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.100.1.tgz",
|
| 337 |
-
"integrity": "sha512-c5FB4nrG7cs1mLSzFGuIVl2iR2YO5XkSJ96uF4zubYm8YDn71XOi2emE9sBm/avfGCj61jaRBLOvxEAVnpys0Q==",
|
| 338 |
-
"license": "MIT",
|
| 339 |
-
"dependencies": {
|
| 340 |
-
"tslib": "2.8.1"
|
| 341 |
-
},
|
| 342 |
-
"engines": {
|
| 343 |
-
"node": ">=20.0.0"
|
| 344 |
-
}
|
| 345 |
-
},
|
| 346 |
-
"node_modules/@supabase/functions-js": {
|
| 347 |
-
"version": "2.100.1",
|
| 348 |
-
"resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.100.1.tgz",
|
| 349 |
-
"integrity": "sha512-mo8QheoV4KR+wSubtyEWhZUxWnCM7YZ23TncccMAlbWAHb8YTDqRGRm9IalWCAswniKyud6buZCk9snRqI86KA==",
|
| 350 |
-
"license": "MIT",
|
| 351 |
-
"dependencies": {
|
| 352 |
-
"tslib": "2.8.1"
|
| 353 |
-
},
|
| 354 |
-
"engines": {
|
| 355 |
-
"node": ">=20.0.0"
|
| 356 |
-
}
|
| 357 |
-
},
|
| 358 |
-
"node_modules/@supabase/phoenix": {
|
| 359 |
-
"version": "0.4.0",
|
| 360 |
-
"resolved": "https://registry.npmjs.org/@supabase/phoenix/-/phoenix-0.4.0.tgz",
|
| 361 |
-
"integrity": "sha512-RHSx8bHS02xwfHdAbX5Lpbo6PXbgyf7lTaXTlwtFDPwOIw64NnVRwFAXGojHhjtVYI+PEPNSWwkL90f4agN3bw==",
|
| 362 |
-
"license": "MIT"
|
| 363 |
-
},
|
| 364 |
-
"node_modules/@supabase/postgrest-js": {
|
| 365 |
-
"version": "2.100.1",
|
| 366 |
-
"resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.100.1.tgz",
|
| 367 |
-
"integrity": "sha512-OIh4mOSo2LdqF2kox76OAPDtcSs+PwKABJOjc6plUV4/LXhFEsI2uwdEEIs7K7fd141qehWEVl/Y+Ts0fNvYsw==",
|
| 368 |
-
"license": "MIT",
|
| 369 |
-
"dependencies": {
|
| 370 |
-
"tslib": "2.8.1"
|
| 371 |
-
},
|
| 372 |
-
"engines": {
|
| 373 |
-
"node": ">=20.0.0"
|
| 374 |
-
}
|
| 375 |
-
},
|
| 376 |
-
"node_modules/@supabase/realtime-js": {
|
| 377 |
-
"version": "2.100.1",
|
| 378 |
-
"resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.100.1.tgz",
|
| 379 |
-
"integrity": "sha512-FHuRWPX4qZQ4x+0Q+ZrKaBZnOiVGiwsgiAUJM98pYRib1yeaE/fOM1lZ1ozd+4gA8Udw23OyaD8SxKS5mT5NYw==",
|
| 380 |
-
"license": "MIT",
|
| 381 |
-
"dependencies": {
|
| 382 |
-
"@supabase/phoenix": "^0.4.0",
|
| 383 |
-
"@types/ws": "^8.18.1",
|
| 384 |
-
"tslib": "2.8.1",
|
| 385 |
-
"ws": "^8.18.2"
|
| 386 |
-
},
|
| 387 |
-
"engines": {
|
| 388 |
-
"node": ">=20.0.0"
|
| 389 |
-
}
|
| 390 |
-
},
|
| 391 |
-
"node_modules/@supabase/storage-js": {
|
| 392 |
-
"version": "2.100.1",
|
| 393 |
-
"resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.100.1.tgz",
|
| 394 |
-
"integrity": "sha512-x9xpEIoWM4xKiAlwfWTgHPSN6N4Y0aS4FVU4F6ZPbq7Gayw08SrtC6/YH/gOr8CjXQr0HxXYXDop2xGTSjubYA==",
|
| 395 |
-
"license": "MIT",
|
| 396 |
-
"dependencies": {
|
| 397 |
-
"iceberg-js": "^0.8.1",
|
| 398 |
-
"tslib": "2.8.1"
|
| 399 |
-
},
|
| 400 |
-
"engines": {
|
| 401 |
-
"node": ">=20.0.0"
|
| 402 |
-
}
|
| 403 |
-
},
|
| 404 |
-
"node_modules/@supabase/supabase-js": {
|
| 405 |
-
"version": "2.100.1",
|
| 406 |
-
"resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.100.1.tgz",
|
| 407 |
-
"integrity": "sha512-CAeFm5sfX8sbTzxoxRafhohreIzl9a7R6qHTck3MrgTqm5M5g/u0IHfEKYzI9w/17r8NINl8UZrw2i08wrO7Iw==",
|
| 408 |
-
"license": "MIT",
|
| 409 |
-
"dependencies": {
|
| 410 |
-
"@supabase/auth-js": "2.100.1",
|
| 411 |
-
"@supabase/functions-js": "2.100.1",
|
| 412 |
-
"@supabase/postgrest-js": "2.100.1",
|
| 413 |
-
"@supabase/realtime-js": "2.100.1",
|
| 414 |
-
"@supabase/storage-js": "2.100.1"
|
| 415 |
-
},
|
| 416 |
-
"engines": {
|
| 417 |
-
"node": ">=20.0.0"
|
| 418 |
-
}
|
| 419 |
-
},
|
| 420 |
-
"node_modules/@swc/counter": {
|
| 421 |
-
"version": "0.1.3",
|
| 422 |
-
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
|
| 423 |
-
"integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==",
|
| 424 |
-
"license": "Apache-2.0"
|
| 425 |
-
},
|
| 426 |
-
"node_modules/@swc/helpers": {
|
| 427 |
-
"version": "0.5.5",
|
| 428 |
-
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz",
|
| 429 |
-
"integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==",
|
| 430 |
-
"license": "Apache-2.0",
|
| 431 |
-
"dependencies": {
|
| 432 |
-
"@swc/counter": "^0.1.3",
|
| 433 |
-
"tslib": "^2.4.0"
|
| 434 |
-
}
|
| 435 |
-
},
|
| 436 |
-
"node_modules/@types/node": {
|
| 437 |
-
"version": "25.5.0",
|
| 438 |
-
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.0.tgz",
|
| 439 |
-
"integrity": "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==",
|
| 440 |
-
"license": "MIT",
|
| 441 |
-
"dependencies": {
|
| 442 |
-
"undici-types": "~7.18.0"
|
| 443 |
-
}
|
| 444 |
-
},
|
| 445 |
-
"node_modules/@types/ws": {
|
| 446 |
-
"version": "8.18.1",
|
| 447 |
-
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
|
| 448 |
-
"integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
|
| 449 |
-
"license": "MIT",
|
| 450 |
-
"dependencies": {
|
| 451 |
-
"@types/node": "*"
|
| 452 |
-
}
|
| 453 |
-
},
|
| 454 |
-
"node_modules/any-promise": {
|
| 455 |
-
"version": "1.3.0",
|
| 456 |
-
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
|
| 457 |
-
"integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
|
| 458 |
-
"dev": true,
|
| 459 |
-
"license": "MIT"
|
| 460 |
-
},
|
| 461 |
-
"node_modules/anymatch": {
|
| 462 |
-
"version": "3.1.3",
|
| 463 |
-
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
| 464 |
-
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
| 465 |
-
"dev": true,
|
| 466 |
-
"license": "ISC",
|
| 467 |
-
"dependencies": {
|
| 468 |
-
"normalize-path": "^3.0.0",
|
| 469 |
-
"picomatch": "^2.0.4"
|
| 470 |
-
},
|
| 471 |
-
"engines": {
|
| 472 |
-
"node": ">= 8"
|
| 473 |
-
}
|
| 474 |
-
},
|
| 475 |
-
"node_modules/arg": {
|
| 476 |
-
"version": "5.0.2",
|
| 477 |
-
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
|
| 478 |
-
"integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
|
| 479 |
-
"dev": true,
|
| 480 |
-
"license": "MIT"
|
| 481 |
-
},
|
| 482 |
-
"node_modules/asap": {
|
| 483 |
-
"version": "2.0.6",
|
| 484 |
-
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
|
| 485 |
-
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
|
| 486 |
-
"license": "MIT"
|
| 487 |
-
},
|
| 488 |
-
"node_modules/asynckit": {
|
| 489 |
-
"version": "0.4.0",
|
| 490 |
-
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
| 491 |
-
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
| 492 |
-
"license": "MIT"
|
| 493 |
-
},
|
| 494 |
-
"node_modules/autoprefixer": {
|
| 495 |
-
"version": "10.4.27",
|
| 496 |
-
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.27.tgz",
|
| 497 |
-
"integrity": "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==",
|
| 498 |
-
"dev": true,
|
| 499 |
-
"funding": [
|
| 500 |
-
{
|
| 501 |
-
"type": "opencollective",
|
| 502 |
-
"url": "https://opencollective.com/postcss/"
|
| 503 |
-
},
|
| 504 |
-
{
|
| 505 |
-
"type": "tidelift",
|
| 506 |
-
"url": "https://tidelift.com/funding/github/npm/autoprefixer"
|
| 507 |
-
},
|
| 508 |
-
{
|
| 509 |
-
"type": "github",
|
| 510 |
-
"url": "https://github.com/sponsors/ai"
|
| 511 |
-
}
|
| 512 |
-
],
|
| 513 |
-
"license": "MIT",
|
| 514 |
-
"dependencies": {
|
| 515 |
-
"browserslist": "^4.28.1",
|
| 516 |
-
"caniuse-lite": "^1.0.30001774",
|
| 517 |
-
"fraction.js": "^5.3.4",
|
| 518 |
-
"picocolors": "^1.1.1",
|
| 519 |
-
"postcss-value-parser": "^4.2.0"
|
| 520 |
-
},
|
| 521 |
-
"bin": {
|
| 522 |
-
"autoprefixer": "bin/autoprefixer"
|
| 523 |
-
},
|
| 524 |
-
"engines": {
|
| 525 |
-
"node": "^10 || ^12 || >=14"
|
| 526 |
-
},
|
| 527 |
-
"peerDependencies": {
|
| 528 |
-
"postcss": "^8.1.0"
|
| 529 |
-
}
|
| 530 |
-
},
|
| 531 |
-
"node_modules/axios": {
|
| 532 |
-
"version": "1.14.0",
|
| 533 |
-
"resolved": "https://registry.npmjs.org/axios/-/axios-1.14.0.tgz",
|
| 534 |
-
"integrity": "sha512-3Y8yrqLSwjuzpXuZ0oIYZ/XGgLwUIBU3uLvbcpb0pidD9ctpShJd43KSlEEkVQg6DS0G9NKyzOvBfUtDKEyHvQ==",
|
| 535 |
-
"license": "MIT",
|
| 536 |
-
"dependencies": {
|
| 537 |
-
"follow-redirects": "^1.15.11",
|
| 538 |
-
"form-data": "^4.0.5",
|
| 539 |
-
"proxy-from-env": "^2.1.0"
|
| 540 |
-
}
|
| 541 |
-
},
|
| 542 |
-
"node_modules/baseline-browser-mapping": {
|
| 543 |
-
"version": "2.10.11",
|
| 544 |
-
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.11.tgz",
|
| 545 |
-
"integrity": "sha512-DAKrHphkJyiGuau/cFieRYhcTFeK/lBuD++C7cZ6KZHbMhBrisoi+EvhQ5RZrIfV5qwsW8kgQ07JIC+MDJRAhg==",
|
| 546 |
-
"dev": true,
|
| 547 |
-
"license": "Apache-2.0",
|
| 548 |
-
"bin": {
|
| 549 |
-
"baseline-browser-mapping": "dist/cli.cjs"
|
| 550 |
-
},
|
| 551 |
-
"engines": {
|
| 552 |
-
"node": ">=6.0.0"
|
| 553 |
-
}
|
| 554 |
-
},
|
| 555 |
-
"node_modules/binary-extensions": {
|
| 556 |
-
"version": "2.3.0",
|
| 557 |
-
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
| 558 |
-
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
|
| 559 |
-
"dev": true,
|
| 560 |
-
"license": "MIT",
|
| 561 |
-
"engines": {
|
| 562 |
-
"node": ">=8"
|
| 563 |
-
},
|
| 564 |
-
"funding": {
|
| 565 |
-
"url": "https://github.com/sponsors/sindresorhus"
|
| 566 |
-
}
|
| 567 |
-
},
|
| 568 |
-
"node_modules/braces": {
|
| 569 |
-
"version": "3.0.3",
|
| 570 |
-
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
| 571 |
-
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
| 572 |
-
"dev": true,
|
| 573 |
-
"license": "MIT",
|
| 574 |
-
"dependencies": {
|
| 575 |
-
"fill-range": "^7.1.1"
|
| 576 |
-
},
|
| 577 |
-
"engines": {
|
| 578 |
-
"node": ">=8"
|
| 579 |
-
}
|
| 580 |
-
},
|
| 581 |
-
"node_modules/browserslist": {
|
| 582 |
-
"version": "4.28.1",
|
| 583 |
-
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
|
| 584 |
-
"integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
|
| 585 |
-
"dev": true,
|
| 586 |
-
"funding": [
|
| 587 |
-
{
|
| 588 |
-
"type": "opencollective",
|
| 589 |
-
"url": "https://opencollective.com/browserslist"
|
| 590 |
-
},
|
| 591 |
-
{
|
| 592 |
-
"type": "tidelift",
|
| 593 |
-
"url": "https://tidelift.com/funding/github/npm/browserslist"
|
| 594 |
-
},
|
| 595 |
-
{
|
| 596 |
-
"type": "github",
|
| 597 |
-
"url": "https://github.com/sponsors/ai"
|
| 598 |
-
}
|
| 599 |
-
],
|
| 600 |
-
"license": "MIT",
|
| 601 |
-
"dependencies": {
|
| 602 |
-
"baseline-browser-mapping": "^2.9.0",
|
| 603 |
-
"caniuse-lite": "^1.0.30001759",
|
| 604 |
-
"electron-to-chromium": "^1.5.263",
|
| 605 |
-
"node-releases": "^2.0.27",
|
| 606 |
-
"update-browserslist-db": "^1.2.0"
|
| 607 |
-
},
|
| 608 |
-
"bin": {
|
| 609 |
-
"browserslist": "cli.js"
|
| 610 |
-
},
|
| 611 |
-
"engines": {
|
| 612 |
-
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
|
| 613 |
-
}
|
| 614 |
-
},
|
| 615 |
-
"node_modules/busboy": {
|
| 616 |
-
"version": "1.6.0",
|
| 617 |
-
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
|
| 618 |
-
"integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
|
| 619 |
-
"dependencies": {
|
| 620 |
-
"streamsearch": "^1.1.0"
|
| 621 |
-
},
|
| 622 |
-
"engines": {
|
| 623 |
-
"node": ">=10.16.0"
|
| 624 |
-
}
|
| 625 |
-
},
|
| 626 |
-
"node_modules/call-bind-apply-helpers": {
|
| 627 |
-
"version": "1.0.2",
|
| 628 |
-
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
| 629 |
-
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
| 630 |
-
"license": "MIT",
|
| 631 |
-
"dependencies": {
|
| 632 |
-
"es-errors": "^1.3.0",
|
| 633 |
-
"function-bind": "^1.1.2"
|
| 634 |
-
},
|
| 635 |
-
"engines": {
|
| 636 |
-
"node": ">= 0.4"
|
| 637 |
-
}
|
| 638 |
-
},
|
| 639 |
-
"node_modules/camelcase-css": {
|
| 640 |
-
"version": "2.0.1",
|
| 641 |
-
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
|
| 642 |
-
"integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
|
| 643 |
-
"dev": true,
|
| 644 |
-
"license": "MIT",
|
| 645 |
-
"engines": {
|
| 646 |
-
"node": ">= 6"
|
| 647 |
-
}
|
| 648 |
-
},
|
| 649 |
-
"node_modules/caniuse-lite": {
|
| 650 |
-
"version": "1.0.30001781",
|
| 651 |
-
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001781.tgz",
|
| 652 |
-
"integrity": "sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw==",
|
| 653 |
-
"funding": [
|
| 654 |
-
{
|
| 655 |
-
"type": "opencollective",
|
| 656 |
-
"url": "https://opencollective.com/browserslist"
|
| 657 |
-
},
|
| 658 |
-
{
|
| 659 |
-
"type": "tidelift",
|
| 660 |
-
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
|
| 661 |
-
},
|
| 662 |
-
{
|
| 663 |
-
"type": "github",
|
| 664 |
-
"url": "https://github.com/sponsors/ai"
|
| 665 |
-
}
|
| 666 |
-
],
|
| 667 |
-
"license": "CC-BY-4.0"
|
| 668 |
-
},
|
| 669 |
-
"node_modules/chart.js": {
|
| 670 |
-
"version": "4.5.1",
|
| 671 |
-
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.1.tgz",
|
| 672 |
-
"integrity": "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==",
|
| 673 |
-
"license": "MIT",
|
| 674 |
-
"dependencies": {
|
| 675 |
-
"@kurkle/color": "^0.3.0"
|
| 676 |
-
},
|
| 677 |
-
"engines": {
|
| 678 |
-
"pnpm": ">=8"
|
| 679 |
-
}
|
| 680 |
-
},
|
| 681 |
-
"node_modules/chokidar": {
|
| 682 |
-
"version": "3.6.0",
|
| 683 |
-
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
| 684 |
-
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
|
| 685 |
-
"dev": true,
|
| 686 |
-
"license": "MIT",
|
| 687 |
-
"dependencies": {
|
| 688 |
-
"anymatch": "~3.1.2",
|
| 689 |
-
"braces": "~3.0.2",
|
| 690 |
-
"glob-parent": "~5.1.2",
|
| 691 |
-
"is-binary-path": "~2.1.0",
|
| 692 |
-
"is-glob": "~4.0.1",
|
| 693 |
-
"normalize-path": "~3.0.0",
|
| 694 |
-
"readdirp": "~3.6.0"
|
| 695 |
-
},
|
| 696 |
-
"engines": {
|
| 697 |
-
"node": ">= 8.10.0"
|
| 698 |
-
},
|
| 699 |
-
"funding": {
|
| 700 |
-
"url": "https://paulmillr.com/funding/"
|
| 701 |
-
},
|
| 702 |
-
"optionalDependencies": {
|
| 703 |
-
"fsevents": "~2.3.2"
|
| 704 |
-
}
|
| 705 |
-
},
|
| 706 |
-
"node_modules/chokidar/node_modules/glob-parent": {
|
| 707 |
-
"version": "5.1.2",
|
| 708 |
-
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
| 709 |
-
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
| 710 |
-
"dev": true,
|
| 711 |
-
"license": "ISC",
|
| 712 |
-
"dependencies": {
|
| 713 |
-
"is-glob": "^4.0.1"
|
| 714 |
-
},
|
| 715 |
-
"engines": {
|
| 716 |
-
"node": ">= 6"
|
| 717 |
-
}
|
| 718 |
-
},
|
| 719 |
-
"node_modules/client-only": {
|
| 720 |
-
"version": "0.0.1",
|
| 721 |
-
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
| 722 |
-
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
|
| 723 |
-
"license": "MIT"
|
| 724 |
-
},
|
| 725 |
-
"node_modules/combined-stream": {
|
| 726 |
-
"version": "1.0.8",
|
| 727 |
-
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
| 728 |
-
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
| 729 |
-
"license": "MIT",
|
| 730 |
-
"dependencies": {
|
| 731 |
-
"delayed-stream": "~1.0.0"
|
| 732 |
-
},
|
| 733 |
-
"engines": {
|
| 734 |
-
"node": ">= 0.8"
|
| 735 |
-
}
|
| 736 |
-
},
|
| 737 |
-
"node_modules/commander": {
|
| 738 |
-
"version": "4.1.1",
|
| 739 |
-
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
|
| 740 |
-
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
|
| 741 |
-
"dev": true,
|
| 742 |
-
"license": "MIT",
|
| 743 |
-
"engines": {
|
| 744 |
-
"node": ">= 6"
|
| 745 |
-
}
|
| 746 |
-
},
|
| 747 |
-
"node_modules/cssesc": {
|
| 748 |
-
"version": "3.0.0",
|
| 749 |
-
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
| 750 |
-
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
|
| 751 |
-
"dev": true,
|
| 752 |
-
"license": "MIT",
|
| 753 |
-
"bin": {
|
| 754 |
-
"cssesc": "bin/cssesc"
|
| 755 |
-
},
|
| 756 |
-
"engines": {
|
| 757 |
-
"node": ">=4"
|
| 758 |
-
}
|
| 759 |
-
},
|
| 760 |
-
"node_modules/deepmerge": {
|
| 761 |
-
"version": "4.3.1",
|
| 762 |
-
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
| 763 |
-
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
|
| 764 |
-
"license": "MIT",
|
| 765 |
-
"engines": {
|
| 766 |
-
"node": ">=0.10.0"
|
| 767 |
-
}
|
| 768 |
-
},
|
| 769 |
-
"node_modules/delayed-stream": {
|
| 770 |
-
"version": "1.0.0",
|
| 771 |
-
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
| 772 |
-
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
| 773 |
-
"license": "MIT",
|
| 774 |
-
"engines": {
|
| 775 |
-
"node": ">=0.4.0"
|
| 776 |
-
}
|
| 777 |
-
},
|
| 778 |
-
"node_modules/dezalgo": {
|
| 779 |
-
"version": "1.0.4",
|
| 780 |
-
"resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
|
| 781 |
-
"integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
|
| 782 |
-
"license": "ISC",
|
| 783 |
-
"dependencies": {
|
| 784 |
-
"asap": "^2.0.0",
|
| 785 |
-
"wrappy": "1"
|
| 786 |
-
}
|
| 787 |
-
},
|
| 788 |
-
"node_modules/didyoumean": {
|
| 789 |
-
"version": "1.2.2",
|
| 790 |
-
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
|
| 791 |
-
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
|
| 792 |
-
"dev": true,
|
| 793 |
-
"license": "Apache-2.0"
|
| 794 |
-
},
|
| 795 |
-
"node_modules/dlv": {
|
| 796 |
-
"version": "1.1.3",
|
| 797 |
-
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
|
| 798 |
-
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
|
| 799 |
-
"dev": true,
|
| 800 |
-
"license": "MIT"
|
| 801 |
-
},
|
| 802 |
-
"node_modules/dunder-proto": {
|
| 803 |
-
"version": "1.0.1",
|
| 804 |
-
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
| 805 |
-
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
| 806 |
-
"license": "MIT",
|
| 807 |
-
"dependencies": {
|
| 808 |
-
"call-bind-apply-helpers": "^1.0.1",
|
| 809 |
-
"es-errors": "^1.3.0",
|
| 810 |
-
"gopd": "^1.2.0"
|
| 811 |
-
},
|
| 812 |
-
"engines": {
|
| 813 |
-
"node": ">= 0.4"
|
| 814 |
-
}
|
| 815 |
-
},
|
| 816 |
-
"node_modules/electron-to-chromium": {
|
| 817 |
-
"version": "1.5.328",
|
| 818 |
-
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.328.tgz",
|
| 819 |
-
"integrity": "sha512-QNQ5l45DzYytThO21403XN3FvK0hOkWDG8viNf6jqS42msJ8I4tGDSpBCgvDRRPnkffafiwAym2X2eHeGD2V0w==",
|
| 820 |
-
"dev": true,
|
| 821 |
-
"license": "ISC"
|
| 822 |
-
},
|
| 823 |
-
"node_modules/es-define-property": {
|
| 824 |
-
"version": "1.0.1",
|
| 825 |
-
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
| 826 |
-
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
| 827 |
-
"license": "MIT",
|
| 828 |
-
"engines": {
|
| 829 |
-
"node": ">= 0.4"
|
| 830 |
-
}
|
| 831 |
-
},
|
| 832 |
-
"node_modules/es-errors": {
|
| 833 |
-
"version": "1.3.0",
|
| 834 |
-
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
| 835 |
-
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
| 836 |
-
"license": "MIT",
|
| 837 |
-
"engines": {
|
| 838 |
-
"node": ">= 0.4"
|
| 839 |
-
}
|
| 840 |
-
},
|
| 841 |
-
"node_modules/es-object-atoms": {
|
| 842 |
-
"version": "1.1.1",
|
| 843 |
-
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
| 844 |
-
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
| 845 |
-
"license": "MIT",
|
| 846 |
-
"dependencies": {
|
| 847 |
-
"es-errors": "^1.3.0"
|
| 848 |
-
},
|
| 849 |
-
"engines": {
|
| 850 |
-
"node": ">= 0.4"
|
| 851 |
-
}
|
| 852 |
-
},
|
| 853 |
-
"node_modules/es-set-tostringtag": {
|
| 854 |
-
"version": "2.1.0",
|
| 855 |
-
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
| 856 |
-
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
| 857 |
-
"license": "MIT",
|
| 858 |
-
"dependencies": {
|
| 859 |
-
"es-errors": "^1.3.0",
|
| 860 |
-
"get-intrinsic": "^1.2.6",
|
| 861 |
-
"has-tostringtag": "^1.0.2",
|
| 862 |
-
"hasown": "^2.0.2"
|
| 863 |
-
},
|
| 864 |
-
"engines": {
|
| 865 |
-
"node": ">= 0.4"
|
| 866 |
-
}
|
| 867 |
-
},
|
| 868 |
-
"node_modules/escalade": {
|
| 869 |
-
"version": "3.2.0",
|
| 870 |
-
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
|
| 871 |
-
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
|
| 872 |
-
"dev": true,
|
| 873 |
-
"license": "MIT",
|
| 874 |
-
"engines": {
|
| 875 |
-
"node": ">=6"
|
| 876 |
-
}
|
| 877 |
-
},
|
| 878 |
-
"node_modules/fast-glob": {
|
| 879 |
-
"version": "3.3.3",
|
| 880 |
-
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
|
| 881 |
-
"integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
|
| 882 |
-
"dev": true,
|
| 883 |
-
"license": "MIT",
|
| 884 |
-
"dependencies": {
|
| 885 |
-
"@nodelib/fs.stat": "^2.0.2",
|
| 886 |
-
"@nodelib/fs.walk": "^1.2.3",
|
| 887 |
-
"glob-parent": "^5.1.2",
|
| 888 |
-
"merge2": "^1.3.0",
|
| 889 |
-
"micromatch": "^4.0.8"
|
| 890 |
-
},
|
| 891 |
-
"engines": {
|
| 892 |
-
"node": ">=8.6.0"
|
| 893 |
-
}
|
| 894 |
-
},
|
| 895 |
-
"node_modules/fast-glob/node_modules/glob-parent": {
|
| 896 |
-
"version": "5.1.2",
|
| 897 |
-
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
| 898 |
-
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
| 899 |
-
"dev": true,
|
| 900 |
-
"license": "ISC",
|
| 901 |
-
"dependencies": {
|
| 902 |
-
"is-glob": "^4.0.1"
|
| 903 |
-
},
|
| 904 |
-
"engines": {
|
| 905 |
-
"node": ">= 6"
|
| 906 |
-
}
|
| 907 |
-
},
|
| 908 |
-
"node_modules/fastq": {
|
| 909 |
-
"version": "1.20.1",
|
| 910 |
-
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
|
| 911 |
-
"integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
|
| 912 |
-
"dev": true,
|
| 913 |
-
"license": "ISC",
|
| 914 |
-
"dependencies": {
|
| 915 |
-
"reusify": "^1.0.4"
|
| 916 |
-
}
|
| 917 |
-
},
|
| 918 |
-
"node_modules/fill-range": {
|
| 919 |
-
"version": "7.1.1",
|
| 920 |
-
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
| 921 |
-
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
| 922 |
-
"dev": true,
|
| 923 |
-
"license": "MIT",
|
| 924 |
-
"dependencies": {
|
| 925 |
-
"to-regex-range": "^5.0.1"
|
| 926 |
-
},
|
| 927 |
-
"engines": {
|
| 928 |
-
"node": ">=8"
|
| 929 |
-
}
|
| 930 |
-
},
|
| 931 |
-
"node_modules/follow-redirects": {
|
| 932 |
-
"version": "1.15.11",
|
| 933 |
-
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
|
| 934 |
-
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
|
| 935 |
-
"funding": [
|
| 936 |
-
{
|
| 937 |
-
"type": "individual",
|
| 938 |
-
"url": "https://github.com/sponsors/RubenVerborgh"
|
| 939 |
-
}
|
| 940 |
-
],
|
| 941 |
-
"license": "MIT",
|
| 942 |
-
"engines": {
|
| 943 |
-
"node": ">=4.0"
|
| 944 |
-
},
|
| 945 |
-
"peerDependenciesMeta": {
|
| 946 |
-
"debug": {
|
| 947 |
-
"optional": true
|
| 948 |
-
}
|
| 949 |
-
}
|
| 950 |
-
},
|
| 951 |
-
"node_modules/form-data": {
|
| 952 |
-
"version": "4.0.5",
|
| 953 |
-
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
|
| 954 |
-
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
|
| 955 |
-
"license": "MIT",
|
| 956 |
-
"dependencies": {
|
| 957 |
-
"asynckit": "^0.4.0",
|
| 958 |
-
"combined-stream": "^1.0.8",
|
| 959 |
-
"es-set-tostringtag": "^2.1.0",
|
| 960 |
-
"hasown": "^2.0.2",
|
| 961 |
-
"mime-types": "^2.1.12"
|
| 962 |
-
},
|
| 963 |
-
"engines": {
|
| 964 |
-
"node": ">= 6"
|
| 965 |
-
}
|
| 966 |
-
},
|
| 967 |
-
"node_modules/formidable": {
|
| 968 |
-
"version": "3.5.4",
|
| 969 |
-
"resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz",
|
| 970 |
-
"integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==",
|
| 971 |
-
"license": "MIT",
|
| 972 |
-
"dependencies": {
|
| 973 |
-
"@paralleldrive/cuid2": "^2.2.2",
|
| 974 |
-
"dezalgo": "^1.0.4",
|
| 975 |
-
"once": "^1.4.0"
|
| 976 |
-
},
|
| 977 |
-
"engines": {
|
| 978 |
-
"node": ">=14.0.0"
|
| 979 |
-
},
|
| 980 |
-
"funding": {
|
| 981 |
-
"url": "https://ko-fi.com/tunnckoCore/commissions"
|
| 982 |
-
}
|
| 983 |
-
},
|
| 984 |
-
"node_modules/fraction.js": {
|
| 985 |
-
"version": "5.3.4",
|
| 986 |
-
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz",
|
| 987 |
-
"integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==",
|
| 988 |
-
"dev": true,
|
| 989 |
-
"license": "MIT",
|
| 990 |
-
"engines": {
|
| 991 |
-
"node": "*"
|
| 992 |
-
},
|
| 993 |
-
"funding": {
|
| 994 |
-
"type": "github",
|
| 995 |
-
"url": "https://github.com/sponsors/rawify"
|
| 996 |
-
}
|
| 997 |
-
},
|
| 998 |
-
"node_modules/fsevents": {
|
| 999 |
-
"version": "2.3.3",
|
| 1000 |
-
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
| 1001 |
-
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
| 1002 |
-
"dev": true,
|
| 1003 |
-
"hasInstallScript": true,
|
| 1004 |
-
"license": "MIT",
|
| 1005 |
-
"optional": true,
|
| 1006 |
-
"os": [
|
| 1007 |
-
"darwin"
|
| 1008 |
-
],
|
| 1009 |
-
"engines": {
|
| 1010 |
-
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
| 1011 |
-
}
|
| 1012 |
-
},
|
| 1013 |
-
"node_modules/function-bind": {
|
| 1014 |
-
"version": "1.1.2",
|
| 1015 |
-
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
| 1016 |
-
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
| 1017 |
-
"license": "MIT",
|
| 1018 |
-
"funding": {
|
| 1019 |
-
"url": "https://github.com/sponsors/ljharb"
|
| 1020 |
-
}
|
| 1021 |
-
},
|
| 1022 |
-
"node_modules/get-intrinsic": {
|
| 1023 |
-
"version": "1.3.0",
|
| 1024 |
-
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
| 1025 |
-
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
| 1026 |
-
"license": "MIT",
|
| 1027 |
-
"dependencies": {
|
| 1028 |
-
"call-bind-apply-helpers": "^1.0.2",
|
| 1029 |
-
"es-define-property": "^1.0.1",
|
| 1030 |
-
"es-errors": "^1.3.0",
|
| 1031 |
-
"es-object-atoms": "^1.1.1",
|
| 1032 |
-
"function-bind": "^1.1.2",
|
| 1033 |
-
"get-proto": "^1.0.1",
|
| 1034 |
-
"gopd": "^1.2.0",
|
| 1035 |
-
"has-symbols": "^1.1.0",
|
| 1036 |
-
"hasown": "^2.0.2",
|
| 1037 |
-
"math-intrinsics": "^1.1.0"
|
| 1038 |
-
},
|
| 1039 |
-
"engines": {
|
| 1040 |
-
"node": ">= 0.4"
|
| 1041 |
-
},
|
| 1042 |
-
"funding": {
|
| 1043 |
-
"url": "https://github.com/sponsors/ljharb"
|
| 1044 |
-
}
|
| 1045 |
-
},
|
| 1046 |
-
"node_modules/get-proto": {
|
| 1047 |
-
"version": "1.0.1",
|
| 1048 |
-
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
| 1049 |
-
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
| 1050 |
-
"license": "MIT",
|
| 1051 |
-
"dependencies": {
|
| 1052 |
-
"dunder-proto": "^1.0.1",
|
| 1053 |
-
"es-object-atoms": "^1.0.0"
|
| 1054 |
-
},
|
| 1055 |
-
"engines": {
|
| 1056 |
-
"node": ">= 0.4"
|
| 1057 |
-
}
|
| 1058 |
-
},
|
| 1059 |
-
"node_modules/git": {
|
| 1060 |
-
"version": "0.1.5",
|
| 1061 |
-
"resolved": "https://registry.npmjs.org/git/-/git-0.1.5.tgz",
|
| 1062 |
-
"integrity": "sha512-N+bfOrXyKMU/fQtCj6D/U9MQOEN0DAA8TLHSLdUQRSWBOkeRvsjJHdrdkvcq05xO7GSDKWc3nDEGoTZ4DfCCSg==",
|
| 1063 |
-
"dependencies": {
|
| 1064 |
-
"mime": "1.2.9"
|
| 1065 |
-
},
|
| 1066 |
-
"engines": {
|
| 1067 |
-
"node": ">=0.4.0"
|
| 1068 |
-
}
|
| 1069 |
-
},
|
| 1070 |
-
"node_modules/glob-parent": {
|
| 1071 |
-
"version": "6.0.2",
|
| 1072 |
-
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
|
| 1073 |
-
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
|
| 1074 |
-
"dev": true,
|
| 1075 |
-
"license": "ISC",
|
| 1076 |
-
"dependencies": {
|
| 1077 |
-
"is-glob": "^4.0.3"
|
| 1078 |
-
},
|
| 1079 |
-
"engines": {
|
| 1080 |
-
"node": ">=10.13.0"
|
| 1081 |
-
}
|
| 1082 |
-
},
|
| 1083 |
-
"node_modules/gopd": {
|
| 1084 |
-
"version": "1.2.0",
|
| 1085 |
-
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
| 1086 |
-
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
| 1087 |
-
"license": "MIT",
|
| 1088 |
-
"engines": {
|
| 1089 |
-
"node": ">= 0.4"
|
| 1090 |
-
},
|
| 1091 |
-
"funding": {
|
| 1092 |
-
"url": "https://github.com/sponsors/ljharb"
|
| 1093 |
-
}
|
| 1094 |
-
},
|
| 1095 |
-
"node_modules/graceful-fs": {
|
| 1096 |
-
"version": "4.2.11",
|
| 1097 |
-
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
| 1098 |
-
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
| 1099 |
-
"license": "ISC"
|
| 1100 |
-
},
|
| 1101 |
-
"node_modules/has-symbols": {
|
| 1102 |
-
"version": "1.1.0",
|
| 1103 |
-
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
| 1104 |
-
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
| 1105 |
-
"license": "MIT",
|
| 1106 |
-
"engines": {
|
| 1107 |
-
"node": ">= 0.4"
|
| 1108 |
-
},
|
| 1109 |
-
"funding": {
|
| 1110 |
-
"url": "https://github.com/sponsors/ljharb"
|
| 1111 |
-
}
|
| 1112 |
-
},
|
| 1113 |
-
"node_modules/has-tostringtag": {
|
| 1114 |
-
"version": "1.0.2",
|
| 1115 |
-
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
| 1116 |
-
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
| 1117 |
-
"license": "MIT",
|
| 1118 |
-
"dependencies": {
|
| 1119 |
-
"has-symbols": "^1.0.3"
|
| 1120 |
-
},
|
| 1121 |
-
"engines": {
|
| 1122 |
-
"node": ">= 0.4"
|
| 1123 |
-
},
|
| 1124 |
-
"funding": {
|
| 1125 |
-
"url": "https://github.com/sponsors/ljharb"
|
| 1126 |
-
}
|
| 1127 |
-
},
|
| 1128 |
-
"node_modules/hasown": {
|
| 1129 |
-
"version": "2.0.2",
|
| 1130 |
-
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
| 1131 |
-
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
| 1132 |
-
"license": "MIT",
|
| 1133 |
-
"dependencies": {
|
| 1134 |
-
"function-bind": "^1.1.2"
|
| 1135 |
-
},
|
| 1136 |
-
"engines": {
|
| 1137 |
-
"node": ">= 0.4"
|
| 1138 |
-
}
|
| 1139 |
-
},
|
| 1140 |
-
"node_modules/iceberg-js": {
|
| 1141 |
-
"version": "0.8.1",
|
| 1142 |
-
"resolved": "https://registry.npmjs.org/iceberg-js/-/iceberg-js-0.8.1.tgz",
|
| 1143 |
-
"integrity": "sha512-1dhVQZXhcHje7798IVM+xoo/1ZdVfzOMIc8/rgVSijRK38EDqOJoGula9N/8ZI5RD8QTxNQtK/Gozpr+qUqRRA==",
|
| 1144 |
-
"license": "MIT",
|
| 1145 |
-
"engines": {
|
| 1146 |
-
"node": ">=20.0.0"
|
| 1147 |
-
}
|
| 1148 |
-
},
|
| 1149 |
-
"node_modules/is-binary-path": {
|
| 1150 |
-
"version": "2.1.0",
|
| 1151 |
-
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
| 1152 |
-
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
| 1153 |
-
"dev": true,
|
| 1154 |
-
"license": "MIT",
|
| 1155 |
-
"dependencies": {
|
| 1156 |
-
"binary-extensions": "^2.0.0"
|
| 1157 |
-
},
|
| 1158 |
-
"engines": {
|
| 1159 |
-
"node": ">=8"
|
| 1160 |
-
}
|
| 1161 |
-
},
|
| 1162 |
-
"node_modules/is-core-module": {
|
| 1163 |
-
"version": "2.16.1",
|
| 1164 |
-
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
|
| 1165 |
-
"integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
|
| 1166 |
-
"dev": true,
|
| 1167 |
-
"license": "MIT",
|
| 1168 |
-
"dependencies": {
|
| 1169 |
-
"hasown": "^2.0.2"
|
| 1170 |
-
},
|
| 1171 |
-
"engines": {
|
| 1172 |
-
"node": ">= 0.4"
|
| 1173 |
-
},
|
| 1174 |
-
"funding": {
|
| 1175 |
-
"url": "https://github.com/sponsors/ljharb"
|
| 1176 |
-
}
|
| 1177 |
-
},
|
| 1178 |
-
"node_modules/is-extglob": {
|
| 1179 |
-
"version": "2.1.1",
|
| 1180 |
-
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
| 1181 |
-
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
| 1182 |
-
"dev": true,
|
| 1183 |
-
"license": "MIT",
|
| 1184 |
-
"engines": {
|
| 1185 |
-
"node": ">=0.10.0"
|
| 1186 |
-
}
|
| 1187 |
-
},
|
| 1188 |
-
"node_modules/is-glob": {
|
| 1189 |
-
"version": "4.0.3",
|
| 1190 |
-
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
| 1191 |
-
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
| 1192 |
-
"dev": true,
|
| 1193 |
-
"license": "MIT",
|
| 1194 |
-
"dependencies": {
|
| 1195 |
-
"is-extglob": "^2.1.1"
|
| 1196 |
-
},
|
| 1197 |
-
"engines": {
|
| 1198 |
-
"node": ">=0.10.0"
|
| 1199 |
-
}
|
| 1200 |
-
},
|
| 1201 |
-
"node_modules/is-number": {
|
| 1202 |
-
"version": "7.0.0",
|
| 1203 |
-
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
| 1204 |
-
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
| 1205 |
-
"dev": true,
|
| 1206 |
-
"license": "MIT",
|
| 1207 |
-
"engines": {
|
| 1208 |
-
"node": ">=0.12.0"
|
| 1209 |
-
}
|
| 1210 |
-
},
|
| 1211 |
-
"node_modules/jiti": {
|
| 1212 |
-
"version": "1.21.7",
|
| 1213 |
-
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
|
| 1214 |
-
"integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
|
| 1215 |
-
"dev": true,
|
| 1216 |
-
"license": "MIT",
|
| 1217 |
-
"bin": {
|
| 1218 |
-
"jiti": "bin/jiti.js"
|
| 1219 |
-
}
|
| 1220 |
-
},
|
| 1221 |
-
"node_modules/js-tokens": {
|
| 1222 |
-
"version": "4.0.0",
|
| 1223 |
-
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
| 1224 |
-
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
| 1225 |
-
"license": "MIT"
|
| 1226 |
-
},
|
| 1227 |
-
"node_modules/lilconfig": {
|
| 1228 |
-
"version": "3.1.3",
|
| 1229 |
-
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
|
| 1230 |
-
"integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
|
| 1231 |
-
"dev": true,
|
| 1232 |
-
"license": "MIT",
|
| 1233 |
-
"engines": {
|
| 1234 |
-
"node": ">=14"
|
| 1235 |
-
},
|
| 1236 |
-
"funding": {
|
| 1237 |
-
"url": "https://github.com/sponsors/antonk52"
|
| 1238 |
-
}
|
| 1239 |
-
},
|
| 1240 |
-
"node_modules/lines-and-columns": {
|
| 1241 |
-
"version": "1.2.4",
|
| 1242 |
-
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
| 1243 |
-
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
|
| 1244 |
-
"dev": true,
|
| 1245 |
-
"license": "MIT"
|
| 1246 |
-
},
|
| 1247 |
-
"node_modules/loose-envify": {
|
| 1248 |
-
"version": "1.4.0",
|
| 1249 |
-
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
| 1250 |
-
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
| 1251 |
-
"license": "MIT",
|
| 1252 |
-
"dependencies": {
|
| 1253 |
-
"js-tokens": "^3.0.0 || ^4.0.0"
|
| 1254 |
-
},
|
| 1255 |
-
"bin": {
|
| 1256 |
-
"loose-envify": "cli.js"
|
| 1257 |
-
}
|
| 1258 |
-
},
|
| 1259 |
-
"node_modules/math-intrinsics": {
|
| 1260 |
-
"version": "1.1.0",
|
| 1261 |
-
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
| 1262 |
-
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
| 1263 |
-
"license": "MIT",
|
| 1264 |
-
"engines": {
|
| 1265 |
-
"node": ">= 0.4"
|
| 1266 |
-
}
|
| 1267 |
-
},
|
| 1268 |
-
"node_modules/merge2": {
|
| 1269 |
-
"version": "1.4.1",
|
| 1270 |
-
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
| 1271 |
-
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
|
| 1272 |
-
"dev": true,
|
| 1273 |
-
"license": "MIT",
|
| 1274 |
-
"engines": {
|
| 1275 |
-
"node": ">= 8"
|
| 1276 |
-
}
|
| 1277 |
-
},
|
| 1278 |
-
"node_modules/micromatch": {
|
| 1279 |
-
"version": "4.0.8",
|
| 1280 |
-
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
| 1281 |
-
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
| 1282 |
-
"dev": true,
|
| 1283 |
-
"license": "MIT",
|
| 1284 |
-
"dependencies": {
|
| 1285 |
-
"braces": "^3.0.3",
|
| 1286 |
-
"picomatch": "^2.3.1"
|
| 1287 |
-
},
|
| 1288 |
-
"engines": {
|
| 1289 |
-
"node": ">=8.6"
|
| 1290 |
-
}
|
| 1291 |
-
},
|
| 1292 |
-
"node_modules/mime": {
|
| 1293 |
-
"version": "1.2.9",
|
| 1294 |
-
"resolved": "https://registry.npmjs.org/mime/-/mime-1.2.9.tgz",
|
| 1295 |
-
"integrity": "sha512-WiLgbHTIq5AYUvU/Luli4mZ1bUcHpGNHyCsbl+KPMg4zt+XUDpQehWjuBjdLaEvDTinvKj/FgfQt3fPoT7j08g=="
|
| 1296 |
-
},
|
| 1297 |
-
"node_modules/mime-db": {
|
| 1298 |
-
"version": "1.52.0",
|
| 1299 |
-
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
| 1300 |
-
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
| 1301 |
-
"license": "MIT",
|
| 1302 |
-
"engines": {
|
| 1303 |
-
"node": ">= 0.6"
|
| 1304 |
-
}
|
| 1305 |
-
},
|
| 1306 |
-
"node_modules/mime-types": {
|
| 1307 |
-
"version": "2.1.35",
|
| 1308 |
-
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
| 1309 |
-
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
| 1310 |
-
"license": "MIT",
|
| 1311 |
-
"dependencies": {
|
| 1312 |
-
"mime-db": "1.52.0"
|
| 1313 |
-
},
|
| 1314 |
-
"engines": {
|
| 1315 |
-
"node": ">= 0.6"
|
| 1316 |
-
}
|
| 1317 |
-
},
|
| 1318 |
-
"node_modules/mz": {
|
| 1319 |
-
"version": "2.7.0",
|
| 1320 |
-
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
|
| 1321 |
-
"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
|
| 1322 |
-
"dev": true,
|
| 1323 |
-
"license": "MIT",
|
| 1324 |
-
"dependencies": {
|
| 1325 |
-
"any-promise": "^1.0.0",
|
| 1326 |
-
"object-assign": "^4.0.1",
|
| 1327 |
-
"thenify-all": "^1.0.0"
|
| 1328 |
-
}
|
| 1329 |
-
},
|
| 1330 |
-
"node_modules/nanoid": {
|
| 1331 |
-
"version": "3.3.11",
|
| 1332 |
-
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
| 1333 |
-
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
|
| 1334 |
-
"funding": [
|
| 1335 |
-
{
|
| 1336 |
-
"type": "github",
|
| 1337 |
-
"url": "https://github.com/sponsors/ai"
|
| 1338 |
-
}
|
| 1339 |
-
],
|
| 1340 |
-
"license": "MIT",
|
| 1341 |
-
"bin": {
|
| 1342 |
-
"nanoid": "bin/nanoid.cjs"
|
| 1343 |
-
},
|
| 1344 |
-
"engines": {
|
| 1345 |
-
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
| 1346 |
-
}
|
| 1347 |
-
},
|
| 1348 |
-
"node_modules/next": {
|
| 1349 |
-
"version": "14.2.35",
|
| 1350 |
-
"resolved": "https://registry.npmjs.org/next/-/next-14.2.35.tgz",
|
| 1351 |
-
"integrity": "sha512-KhYd2Hjt/O1/1aZVX3dCwGXM1QmOV4eNM2UTacK5gipDdPN/oHHK/4oVGy7X8GMfPMsUTUEmGlsy0EY1YGAkig==",
|
| 1352 |
-
"license": "MIT",
|
| 1353 |
-
"dependencies": {
|
| 1354 |
-
"@next/env": "14.2.35",
|
| 1355 |
-
"@swc/helpers": "0.5.5",
|
| 1356 |
-
"busboy": "1.6.0",
|
| 1357 |
-
"caniuse-lite": "^1.0.30001579",
|
| 1358 |
-
"graceful-fs": "^4.2.11",
|
| 1359 |
-
"postcss": "8.4.31",
|
| 1360 |
-
"styled-jsx": "5.1.1"
|
| 1361 |
-
},
|
| 1362 |
-
"bin": {
|
| 1363 |
-
"next": "dist/bin/next"
|
| 1364 |
-
},
|
| 1365 |
-
"engines": {
|
| 1366 |
-
"node": ">=18.17.0"
|
| 1367 |
-
},
|
| 1368 |
-
"optionalDependencies": {
|
| 1369 |
-
"@next/swc-darwin-arm64": "14.2.33",
|
| 1370 |
-
"@next/swc-darwin-x64": "14.2.33",
|
| 1371 |
-
"@next/swc-linux-arm64-gnu": "14.2.33",
|
| 1372 |
-
"@next/swc-linux-arm64-musl": "14.2.33",
|
| 1373 |
-
"@next/swc-linux-x64-gnu": "14.2.33",
|
| 1374 |
-
"@next/swc-linux-x64-musl": "14.2.33",
|
| 1375 |
-
"@next/swc-win32-arm64-msvc": "14.2.33",
|
| 1376 |
-
"@next/swc-win32-ia32-msvc": "14.2.33",
|
| 1377 |
-
"@next/swc-win32-x64-msvc": "14.2.33"
|
| 1378 |
-
},
|
| 1379 |
-
"peerDependencies": {
|
| 1380 |
-
"@opentelemetry/api": "^1.1.0",
|
| 1381 |
-
"@playwright/test": "^1.41.2",
|
| 1382 |
-
"react": "^18.2.0",
|
| 1383 |
-
"react-dom": "^18.2.0",
|
| 1384 |
-
"sass": "^1.3.0"
|
| 1385 |
-
},
|
| 1386 |
-
"peerDependenciesMeta": {
|
| 1387 |
-
"@opentelemetry/api": {
|
| 1388 |
-
"optional": true
|
| 1389 |
-
},
|
| 1390 |
-
"@playwright/test": {
|
| 1391 |
-
"optional": true
|
| 1392 |
-
},
|
| 1393 |
-
"sass": {
|
| 1394 |
-
"optional": true
|
| 1395 |
-
}
|
| 1396 |
-
}
|
| 1397 |
-
},
|
| 1398 |
-
"node_modules/next/node_modules/postcss": {
|
| 1399 |
-
"version": "8.4.31",
|
| 1400 |
-
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
|
| 1401 |
-
"integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
|
| 1402 |
-
"funding": [
|
| 1403 |
-
{
|
| 1404 |
-
"type": "opencollective",
|
| 1405 |
-
"url": "https://opencollective.com/postcss/"
|
| 1406 |
-
},
|
| 1407 |
-
{
|
| 1408 |
-
"type": "tidelift",
|
| 1409 |
-
"url": "https://tidelift.com/funding/github/npm/postcss"
|
| 1410 |
-
},
|
| 1411 |
-
{
|
| 1412 |
-
"type": "github",
|
| 1413 |
-
"url": "https://github.com/sponsors/ai"
|
| 1414 |
-
}
|
| 1415 |
-
],
|
| 1416 |
-
"license": "MIT",
|
| 1417 |
-
"dependencies": {
|
| 1418 |
-
"nanoid": "^3.3.6",
|
| 1419 |
-
"picocolors": "^1.0.0",
|
| 1420 |
-
"source-map-js": "^1.0.2"
|
| 1421 |
-
},
|
| 1422 |
-
"engines": {
|
| 1423 |
-
"node": "^10 || ^12 || >=14"
|
| 1424 |
-
}
|
| 1425 |
-
},
|
| 1426 |
-
"node_modules/node-releases": {
|
| 1427 |
-
"version": "2.0.36",
|
| 1428 |
-
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz",
|
| 1429 |
-
"integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==",
|
| 1430 |
-
"dev": true,
|
| 1431 |
-
"license": "MIT"
|
| 1432 |
-
},
|
| 1433 |
-
"node_modules/normalize-path": {
|
| 1434 |
-
"version": "3.0.0",
|
| 1435 |
-
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
| 1436 |
-
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
| 1437 |
-
"dev": true,
|
| 1438 |
-
"license": "MIT",
|
| 1439 |
-
"engines": {
|
| 1440 |
-
"node": ">=0.10.0"
|
| 1441 |
-
}
|
| 1442 |
-
},
|
| 1443 |
-
"node_modules/object-assign": {
|
| 1444 |
-
"version": "4.1.1",
|
| 1445 |
-
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
| 1446 |
-
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
| 1447 |
-
"dev": true,
|
| 1448 |
-
"license": "MIT",
|
| 1449 |
-
"engines": {
|
| 1450 |
-
"node": ">=0.10.0"
|
| 1451 |
-
}
|
| 1452 |
-
},
|
| 1453 |
-
"node_modules/object-hash": {
|
| 1454 |
-
"version": "3.0.0",
|
| 1455 |
-
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
|
| 1456 |
-
"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
|
| 1457 |
-
"dev": true,
|
| 1458 |
-
"license": "MIT",
|
| 1459 |
-
"engines": {
|
| 1460 |
-
"node": ">= 6"
|
| 1461 |
-
}
|
| 1462 |
-
},
|
| 1463 |
-
"node_modules/once": {
|
| 1464 |
-
"version": "1.4.0",
|
| 1465 |
-
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
| 1466 |
-
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
| 1467 |
-
"license": "ISC",
|
| 1468 |
-
"dependencies": {
|
| 1469 |
-
"wrappy": "1"
|
| 1470 |
-
}
|
| 1471 |
-
},
|
| 1472 |
-
"node_modules/path-parse": {
|
| 1473 |
-
"version": "1.0.7",
|
| 1474 |
-
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
| 1475 |
-
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
| 1476 |
-
"dev": true,
|
| 1477 |
-
"license": "MIT"
|
| 1478 |
-
},
|
| 1479 |
-
"node_modules/picocolors": {
|
| 1480 |
-
"version": "1.1.1",
|
| 1481 |
-
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
| 1482 |
-
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
|
| 1483 |
-
"license": "ISC"
|
| 1484 |
-
},
|
| 1485 |
-
"node_modules/picomatch": {
|
| 1486 |
-
"version": "2.3.2",
|
| 1487 |
-
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
|
| 1488 |
-
"integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
|
| 1489 |
-
"dev": true,
|
| 1490 |
-
"license": "MIT",
|
| 1491 |
-
"engines": {
|
| 1492 |
-
"node": ">=8.6"
|
| 1493 |
-
},
|
| 1494 |
-
"funding": {
|
| 1495 |
-
"url": "https://github.com/sponsors/jonschlinkert"
|
| 1496 |
-
}
|
| 1497 |
-
},
|
| 1498 |
-
"node_modules/pify": {
|
| 1499 |
-
"version": "2.3.0",
|
| 1500 |
-
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
| 1501 |
-
"integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
|
| 1502 |
-
"dev": true,
|
| 1503 |
-
"license": "MIT",
|
| 1504 |
-
"engines": {
|
| 1505 |
-
"node": ">=0.10.0"
|
| 1506 |
-
}
|
| 1507 |
-
},
|
| 1508 |
-
"node_modules/pirates": {
|
| 1509 |
-
"version": "4.0.7",
|
| 1510 |
-
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
|
| 1511 |
-
"integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
|
| 1512 |
-
"dev": true,
|
| 1513 |
-
"license": "MIT",
|
| 1514 |
-
"engines": {
|
| 1515 |
-
"node": ">= 6"
|
| 1516 |
-
}
|
| 1517 |
-
},
|
| 1518 |
-
"node_modules/postcss": {
|
| 1519 |
-
"version": "8.5.8",
|
| 1520 |
-
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
|
| 1521 |
-
"integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
|
| 1522 |
-
"dev": true,
|
| 1523 |
-
"funding": [
|
| 1524 |
-
{
|
| 1525 |
-
"type": "opencollective",
|
| 1526 |
-
"url": "https://opencollective.com/postcss/"
|
| 1527 |
-
},
|
| 1528 |
-
{
|
| 1529 |
-
"type": "tidelift",
|
| 1530 |
-
"url": "https://tidelift.com/funding/github/npm/postcss"
|
| 1531 |
-
},
|
| 1532 |
-
{
|
| 1533 |
-
"type": "github",
|
| 1534 |
-
"url": "https://github.com/sponsors/ai"
|
| 1535 |
-
}
|
| 1536 |
-
],
|
| 1537 |
-
"license": "MIT",
|
| 1538 |
-
"dependencies": {
|
| 1539 |
-
"nanoid": "^3.3.11",
|
| 1540 |
-
"picocolors": "^1.1.1",
|
| 1541 |
-
"source-map-js": "^1.2.1"
|
| 1542 |
-
},
|
| 1543 |
-
"engines": {
|
| 1544 |
-
"node": "^10 || ^12 || >=14"
|
| 1545 |
-
}
|
| 1546 |
-
},
|
| 1547 |
-
"node_modules/postcss-import": {
|
| 1548 |
-
"version": "15.1.0",
|
| 1549 |
-
"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
|
| 1550 |
-
"integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
|
| 1551 |
-
"dev": true,
|
| 1552 |
-
"license": "MIT",
|
| 1553 |
-
"dependencies": {
|
| 1554 |
-
"postcss-value-parser": "^4.0.0",
|
| 1555 |
-
"read-cache": "^1.0.0",
|
| 1556 |
-
"resolve": "^1.1.7"
|
| 1557 |
-
},
|
| 1558 |
-
"engines": {
|
| 1559 |
-
"node": ">=14.0.0"
|
| 1560 |
-
},
|
| 1561 |
-
"peerDependencies": {
|
| 1562 |
-
"postcss": "^8.0.0"
|
| 1563 |
-
}
|
| 1564 |
-
},
|
| 1565 |
-
"node_modules/postcss-js": {
|
| 1566 |
-
"version": "4.1.0",
|
| 1567 |
-
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz",
|
| 1568 |
-
"integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==",
|
| 1569 |
-
"dev": true,
|
| 1570 |
-
"funding": [
|
| 1571 |
-
{
|
| 1572 |
-
"type": "opencollective",
|
| 1573 |
-
"url": "https://opencollective.com/postcss/"
|
| 1574 |
-
},
|
| 1575 |
-
{
|
| 1576 |
-
"type": "github",
|
| 1577 |
-
"url": "https://github.com/sponsors/ai"
|
| 1578 |
-
}
|
| 1579 |
-
],
|
| 1580 |
-
"license": "MIT",
|
| 1581 |
-
"dependencies": {
|
| 1582 |
-
"camelcase-css": "^2.0.1"
|
| 1583 |
-
},
|
| 1584 |
-
"engines": {
|
| 1585 |
-
"node": "^12 || ^14 || >= 16"
|
| 1586 |
-
},
|
| 1587 |
-
"peerDependencies": {
|
| 1588 |
-
"postcss": "^8.4.21"
|
| 1589 |
-
}
|
| 1590 |
-
},
|
| 1591 |
-
"node_modules/postcss-load-config": {
|
| 1592 |
-
"version": "6.0.1",
|
| 1593 |
-
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz",
|
| 1594 |
-
"integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==",
|
| 1595 |
-
"dev": true,
|
| 1596 |
-
"funding": [
|
| 1597 |
-
{
|
| 1598 |
-
"type": "opencollective",
|
| 1599 |
-
"url": "https://opencollective.com/postcss/"
|
| 1600 |
-
},
|
| 1601 |
-
{
|
| 1602 |
-
"type": "github",
|
| 1603 |
-
"url": "https://github.com/sponsors/ai"
|
| 1604 |
-
}
|
| 1605 |
-
],
|
| 1606 |
-
"license": "MIT",
|
| 1607 |
-
"dependencies": {
|
| 1608 |
-
"lilconfig": "^3.1.1"
|
| 1609 |
-
},
|
| 1610 |
-
"engines": {
|
| 1611 |
-
"node": ">= 18"
|
| 1612 |
-
},
|
| 1613 |
-
"peerDependencies": {
|
| 1614 |
-
"jiti": ">=1.21.0",
|
| 1615 |
-
"postcss": ">=8.0.9",
|
| 1616 |
-
"tsx": "^4.8.1",
|
| 1617 |
-
"yaml": "^2.4.2"
|
| 1618 |
-
},
|
| 1619 |
-
"peerDependenciesMeta": {
|
| 1620 |
-
"jiti": {
|
| 1621 |
-
"optional": true
|
| 1622 |
-
},
|
| 1623 |
-
"postcss": {
|
| 1624 |
-
"optional": true
|
| 1625 |
-
},
|
| 1626 |
-
"tsx": {
|
| 1627 |
-
"optional": true
|
| 1628 |
-
},
|
| 1629 |
-
"yaml": {
|
| 1630 |
-
"optional": true
|
| 1631 |
-
}
|
| 1632 |
-
}
|
| 1633 |
-
},
|
| 1634 |
-
"node_modules/postcss-nested": {
|
| 1635 |
-
"version": "6.2.0",
|
| 1636 |
-
"resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
|
| 1637 |
-
"integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
|
| 1638 |
-
"dev": true,
|
| 1639 |
-
"funding": [
|
| 1640 |
-
{
|
| 1641 |
-
"type": "opencollective",
|
| 1642 |
-
"url": "https://opencollective.com/postcss/"
|
| 1643 |
-
},
|
| 1644 |
-
{
|
| 1645 |
-
"type": "github",
|
| 1646 |
-
"url": "https://github.com/sponsors/ai"
|
| 1647 |
-
}
|
| 1648 |
-
],
|
| 1649 |
-
"license": "MIT",
|
| 1650 |
-
"dependencies": {
|
| 1651 |
-
"postcss-selector-parser": "^6.1.1"
|
| 1652 |
-
},
|
| 1653 |
-
"engines": {
|
| 1654 |
-
"node": ">=12.0"
|
| 1655 |
-
},
|
| 1656 |
-
"peerDependencies": {
|
| 1657 |
-
"postcss": "^8.2.14"
|
| 1658 |
-
}
|
| 1659 |
-
},
|
| 1660 |
-
"node_modules/postcss-selector-parser": {
|
| 1661 |
-
"version": "6.1.2",
|
| 1662 |
-
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
|
| 1663 |
-
"integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
|
| 1664 |
-
"dev": true,
|
| 1665 |
-
"license": "MIT",
|
| 1666 |
-
"dependencies": {
|
| 1667 |
-
"cssesc": "^3.0.0",
|
| 1668 |
-
"util-deprecate": "^1.0.2"
|
| 1669 |
-
},
|
| 1670 |
-
"engines": {
|
| 1671 |
-
"node": ">=4"
|
| 1672 |
-
}
|
| 1673 |
-
},
|
| 1674 |
-
"node_modules/postcss-value-parser": {
|
| 1675 |
-
"version": "4.2.0",
|
| 1676 |
-
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
|
| 1677 |
-
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
|
| 1678 |
-
"dev": true,
|
| 1679 |
-
"license": "MIT"
|
| 1680 |
-
},
|
| 1681 |
-
"node_modules/proxy-from-env": {
|
| 1682 |
-
"version": "2.1.0",
|
| 1683 |
-
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
|
| 1684 |
-
"integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
|
| 1685 |
-
"license": "MIT",
|
| 1686 |
-
"engines": {
|
| 1687 |
-
"node": ">=10"
|
| 1688 |
-
}
|
| 1689 |
-
},
|
| 1690 |
-
"node_modules/queue-microtask": {
|
| 1691 |
-
"version": "1.2.3",
|
| 1692 |
-
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
| 1693 |
-
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
| 1694 |
-
"dev": true,
|
| 1695 |
-
"funding": [
|
| 1696 |
-
{
|
| 1697 |
-
"type": "github",
|
| 1698 |
-
"url": "https://github.com/sponsors/feross"
|
| 1699 |
-
},
|
| 1700 |
-
{
|
| 1701 |
-
"type": "patreon",
|
| 1702 |
-
"url": "https://www.patreon.com/feross"
|
| 1703 |
-
},
|
| 1704 |
-
{
|
| 1705 |
-
"type": "consulting",
|
| 1706 |
-
"url": "https://feross.org/support"
|
| 1707 |
-
}
|
| 1708 |
-
],
|
| 1709 |
-
"license": "MIT"
|
| 1710 |
-
},
|
| 1711 |
-
"node_modules/react": {
|
| 1712 |
-
"version": "18.3.1",
|
| 1713 |
-
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
| 1714 |
-
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
| 1715 |
-
"license": "MIT",
|
| 1716 |
-
"dependencies": {
|
| 1717 |
-
"loose-envify": "^1.1.0"
|
| 1718 |
-
},
|
| 1719 |
-
"engines": {
|
| 1720 |
-
"node": ">=0.10.0"
|
| 1721 |
-
}
|
| 1722 |
-
},
|
| 1723 |
-
"node_modules/react-chartjs-2": {
|
| 1724 |
-
"version": "5.3.1",
|
| 1725 |
-
"resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.3.1.tgz",
|
| 1726 |
-
"integrity": "sha512-h5IPXKg9EXpjoBzUfyWJvllMjG2mQ4EiuHQFhms/AjUm0XSZHhyRy2xVmLXHKrtcdrPO4mnGqRtYoD0vp95A0A==",
|
| 1727 |
-
"license": "MIT",
|
| 1728 |
-
"peerDependencies": {
|
| 1729 |
-
"chart.js": "^4.1.1",
|
| 1730 |
-
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
| 1731 |
-
}
|
| 1732 |
-
},
|
| 1733 |
-
"node_modules/react-dom": {
|
| 1734 |
-
"version": "18.3.1",
|
| 1735 |
-
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
| 1736 |
-
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
| 1737 |
-
"license": "MIT",
|
| 1738 |
-
"dependencies": {
|
| 1739 |
-
"loose-envify": "^1.1.0",
|
| 1740 |
-
"scheduler": "^0.23.2"
|
| 1741 |
-
},
|
| 1742 |
-
"peerDependencies": {
|
| 1743 |
-
"react": "^18.3.1"
|
| 1744 |
-
}
|
| 1745 |
-
},
|
| 1746 |
-
"node_modules/read-cache": {
|
| 1747 |
-
"version": "1.0.0",
|
| 1748 |
-
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
| 1749 |
-
"integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
|
| 1750 |
-
"dev": true,
|
| 1751 |
-
"license": "MIT",
|
| 1752 |
-
"dependencies": {
|
| 1753 |
-
"pify": "^2.3.0"
|
| 1754 |
-
}
|
| 1755 |
-
},
|
| 1756 |
-
"node_modules/readdirp": {
|
| 1757 |
-
"version": "3.6.0",
|
| 1758 |
-
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
| 1759 |
-
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
| 1760 |
-
"dev": true,
|
| 1761 |
-
"license": "MIT",
|
| 1762 |
-
"dependencies": {
|
| 1763 |
-
"picomatch": "^2.2.1"
|
| 1764 |
-
},
|
| 1765 |
-
"engines": {
|
| 1766 |
-
"node": ">=8.10.0"
|
| 1767 |
-
}
|
| 1768 |
-
},
|
| 1769 |
-
"node_modules/resolve": {
|
| 1770 |
-
"version": "1.22.11",
|
| 1771 |
-
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
|
| 1772 |
-
"integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==",
|
| 1773 |
-
"dev": true,
|
| 1774 |
-
"license": "MIT",
|
| 1775 |
-
"dependencies": {
|
| 1776 |
-
"is-core-module": "^2.16.1",
|
| 1777 |
-
"path-parse": "^1.0.7",
|
| 1778 |
-
"supports-preserve-symlinks-flag": "^1.0.0"
|
| 1779 |
-
},
|
| 1780 |
-
"bin": {
|
| 1781 |
-
"resolve": "bin/resolve"
|
| 1782 |
-
},
|
| 1783 |
-
"engines": {
|
| 1784 |
-
"node": ">= 0.4"
|
| 1785 |
-
},
|
| 1786 |
-
"funding": {
|
| 1787 |
-
"url": "https://github.com/sponsors/ljharb"
|
| 1788 |
-
}
|
| 1789 |
-
},
|
| 1790 |
-
"node_modules/reusify": {
|
| 1791 |
-
"version": "1.1.0",
|
| 1792 |
-
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
|
| 1793 |
-
"integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
|
| 1794 |
-
"dev": true,
|
| 1795 |
-
"license": "MIT",
|
| 1796 |
-
"engines": {
|
| 1797 |
-
"iojs": ">=1.0.0",
|
| 1798 |
-
"node": ">=0.10.0"
|
| 1799 |
-
}
|
| 1800 |
-
},
|
| 1801 |
-
"node_modules/run-parallel": {
|
| 1802 |
-
"version": "1.2.0",
|
| 1803 |
-
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
| 1804 |
-
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
|
| 1805 |
-
"dev": true,
|
| 1806 |
-
"funding": [
|
| 1807 |
-
{
|
| 1808 |
-
"type": "github",
|
| 1809 |
-
"url": "https://github.com/sponsors/feross"
|
| 1810 |
-
},
|
| 1811 |
-
{
|
| 1812 |
-
"type": "patreon",
|
| 1813 |
-
"url": "https://www.patreon.com/feross"
|
| 1814 |
-
},
|
| 1815 |
-
{
|
| 1816 |
-
"type": "consulting",
|
| 1817 |
-
"url": "https://feross.org/support"
|
| 1818 |
-
}
|
| 1819 |
-
],
|
| 1820 |
-
"license": "MIT",
|
| 1821 |
-
"dependencies": {
|
| 1822 |
-
"queue-microtask": "^1.2.2"
|
| 1823 |
-
}
|
| 1824 |
-
},
|
| 1825 |
-
"node_modules/scheduler": {
|
| 1826 |
-
"version": "0.23.2",
|
| 1827 |
-
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
|
| 1828 |
-
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
|
| 1829 |
-
"license": "MIT",
|
| 1830 |
-
"dependencies": {
|
| 1831 |
-
"loose-envify": "^1.1.0"
|
| 1832 |
-
}
|
| 1833 |
-
},
|
| 1834 |
-
"node_modules/source-map-js": {
|
| 1835 |
-
"version": "1.2.1",
|
| 1836 |
-
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
| 1837 |
-
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
| 1838 |
-
"license": "BSD-3-Clause",
|
| 1839 |
-
"engines": {
|
| 1840 |
-
"node": ">=0.10.0"
|
| 1841 |
-
}
|
| 1842 |
-
},
|
| 1843 |
-
"node_modules/streamsearch": {
|
| 1844 |
-
"version": "1.1.0",
|
| 1845 |
-
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
|
| 1846 |
-
"integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
|
| 1847 |
-
"engines": {
|
| 1848 |
-
"node": ">=10.0.0"
|
| 1849 |
-
}
|
| 1850 |
-
},
|
| 1851 |
-
"node_modules/styled-jsx": {
|
| 1852 |
-
"version": "5.1.1",
|
| 1853 |
-
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz",
|
| 1854 |
-
"integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==",
|
| 1855 |
-
"license": "MIT",
|
| 1856 |
-
"dependencies": {
|
| 1857 |
-
"client-only": "0.0.1"
|
| 1858 |
-
},
|
| 1859 |
-
"engines": {
|
| 1860 |
-
"node": ">= 12.0.0"
|
| 1861 |
-
},
|
| 1862 |
-
"peerDependencies": {
|
| 1863 |
-
"react": ">= 16.8.0 || 17.x.x || ^18.0.0-0"
|
| 1864 |
-
},
|
| 1865 |
-
"peerDependenciesMeta": {
|
| 1866 |
-
"@babel/core": {
|
| 1867 |
-
"optional": true
|
| 1868 |
-
},
|
| 1869 |
-
"babel-plugin-macros": {
|
| 1870 |
-
"optional": true
|
| 1871 |
-
}
|
| 1872 |
-
}
|
| 1873 |
-
},
|
| 1874 |
-
"node_modules/sucrase": {
|
| 1875 |
-
"version": "3.35.1",
|
| 1876 |
-
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz",
|
| 1877 |
-
"integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==",
|
| 1878 |
-
"dev": true,
|
| 1879 |
-
"license": "MIT",
|
| 1880 |
-
"dependencies": {
|
| 1881 |
-
"@jridgewell/gen-mapping": "^0.3.2",
|
| 1882 |
-
"commander": "^4.0.0",
|
| 1883 |
-
"lines-and-columns": "^1.1.6",
|
| 1884 |
-
"mz": "^2.7.0",
|
| 1885 |
-
"pirates": "^4.0.1",
|
| 1886 |
-
"tinyglobby": "^0.2.11",
|
| 1887 |
-
"ts-interface-checker": "^0.1.9"
|
| 1888 |
-
},
|
| 1889 |
-
"bin": {
|
| 1890 |
-
"sucrase": "bin/sucrase",
|
| 1891 |
-
"sucrase-node": "bin/sucrase-node"
|
| 1892 |
-
},
|
| 1893 |
-
"engines": {
|
| 1894 |
-
"node": ">=16 || 14 >=14.17"
|
| 1895 |
-
}
|
| 1896 |
-
},
|
| 1897 |
-
"node_modules/supports-preserve-symlinks-flag": {
|
| 1898 |
-
"version": "1.0.0",
|
| 1899 |
-
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
| 1900 |
-
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
|
| 1901 |
-
"dev": true,
|
| 1902 |
-
"license": "MIT",
|
| 1903 |
-
"engines": {
|
| 1904 |
-
"node": ">= 0.4"
|
| 1905 |
-
},
|
| 1906 |
-
"funding": {
|
| 1907 |
-
"url": "https://github.com/sponsors/ljharb"
|
| 1908 |
-
}
|
| 1909 |
-
},
|
| 1910 |
-
"node_modules/tailwindcss": {
|
| 1911 |
-
"version": "3.4.19",
|
| 1912 |
-
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz",
|
| 1913 |
-
"integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==",
|
| 1914 |
-
"dev": true,
|
| 1915 |
-
"license": "MIT",
|
| 1916 |
-
"dependencies": {
|
| 1917 |
-
"@alloc/quick-lru": "^5.2.0",
|
| 1918 |
-
"arg": "^5.0.2",
|
| 1919 |
-
"chokidar": "^3.6.0",
|
| 1920 |
-
"didyoumean": "^1.2.2",
|
| 1921 |
-
"dlv": "^1.1.3",
|
| 1922 |
-
"fast-glob": "^3.3.2",
|
| 1923 |
-
"glob-parent": "^6.0.2",
|
| 1924 |
-
"is-glob": "^4.0.3",
|
| 1925 |
-
"jiti": "^1.21.7",
|
| 1926 |
-
"lilconfig": "^3.1.3",
|
| 1927 |
-
"micromatch": "^4.0.8",
|
| 1928 |
-
"normalize-path": "^3.0.0",
|
| 1929 |
-
"object-hash": "^3.0.0",
|
| 1930 |
-
"picocolors": "^1.1.1",
|
| 1931 |
-
"postcss": "^8.4.47",
|
| 1932 |
-
"postcss-import": "^15.1.0",
|
| 1933 |
-
"postcss-js": "^4.0.1",
|
| 1934 |
-
"postcss-load-config": "^4.0.2 || ^5.0 || ^6.0",
|
| 1935 |
-
"postcss-nested": "^6.2.0",
|
| 1936 |
-
"postcss-selector-parser": "^6.1.2",
|
| 1937 |
-
"resolve": "^1.22.8",
|
| 1938 |
-
"sucrase": "^3.35.0"
|
| 1939 |
-
},
|
| 1940 |
-
"bin": {
|
| 1941 |
-
"tailwind": "lib/cli.js",
|
| 1942 |
-
"tailwindcss": "lib/cli.js"
|
| 1943 |
-
},
|
| 1944 |
-
"engines": {
|
| 1945 |
-
"node": ">=14.0.0"
|
| 1946 |
-
}
|
| 1947 |
-
},
|
| 1948 |
-
"node_modules/thenify": {
|
| 1949 |
-
"version": "3.3.1",
|
| 1950 |
-
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
|
| 1951 |
-
"integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
|
| 1952 |
-
"dev": true,
|
| 1953 |
-
"license": "MIT",
|
| 1954 |
-
"dependencies": {
|
| 1955 |
-
"any-promise": "^1.0.0"
|
| 1956 |
-
}
|
| 1957 |
-
},
|
| 1958 |
-
"node_modules/thenify-all": {
|
| 1959 |
-
"version": "1.6.0",
|
| 1960 |
-
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
|
| 1961 |
-
"integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
|
| 1962 |
-
"dev": true,
|
| 1963 |
-
"license": "MIT",
|
| 1964 |
-
"dependencies": {
|
| 1965 |
-
"thenify": ">= 3.1.0 < 4"
|
| 1966 |
-
},
|
| 1967 |
-
"engines": {
|
| 1968 |
-
"node": ">=0.8"
|
| 1969 |
-
}
|
| 1970 |
-
},
|
| 1971 |
-
"node_modules/tinyglobby": {
|
| 1972 |
-
"version": "0.2.15",
|
| 1973 |
-
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
| 1974 |
-
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
|
| 1975 |
-
"dev": true,
|
| 1976 |
-
"license": "MIT",
|
| 1977 |
-
"dependencies": {
|
| 1978 |
-
"fdir": "^6.5.0",
|
| 1979 |
-
"picomatch": "^4.0.3"
|
| 1980 |
-
},
|
| 1981 |
-
"engines": {
|
| 1982 |
-
"node": ">=12.0.0"
|
| 1983 |
-
},
|
| 1984 |
-
"funding": {
|
| 1985 |
-
"url": "https://github.com/sponsors/SuperchupuDev"
|
| 1986 |
-
}
|
| 1987 |
-
},
|
| 1988 |
-
"node_modules/tinyglobby/node_modules/fdir": {
|
| 1989 |
-
"version": "6.5.0",
|
| 1990 |
-
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
|
| 1991 |
-
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
|
| 1992 |
-
"dev": true,
|
| 1993 |
-
"license": "MIT",
|
| 1994 |
-
"engines": {
|
| 1995 |
-
"node": ">=12.0.0"
|
| 1996 |
-
},
|
| 1997 |
-
"peerDependencies": {
|
| 1998 |
-
"picomatch": "^3 || ^4"
|
| 1999 |
-
},
|
| 2000 |
-
"peerDependenciesMeta": {
|
| 2001 |
-
"picomatch": {
|
| 2002 |
-
"optional": true
|
| 2003 |
-
}
|
| 2004 |
-
}
|
| 2005 |
-
},
|
| 2006 |
-
"node_modules/tinyglobby/node_modules/picomatch": {
|
| 2007 |
-
"version": "4.0.4",
|
| 2008 |
-
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
|
| 2009 |
-
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
|
| 2010 |
-
"dev": true,
|
| 2011 |
-
"license": "MIT",
|
| 2012 |
-
"engines": {
|
| 2013 |
-
"node": ">=12"
|
| 2014 |
-
},
|
| 2015 |
-
"funding": {
|
| 2016 |
-
"url": "https://github.com/sponsors/jonschlinkert"
|
| 2017 |
-
}
|
| 2018 |
-
},
|
| 2019 |
-
"node_modules/to-regex-range": {
|
| 2020 |
-
"version": "5.0.1",
|
| 2021 |
-
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
| 2022 |
-
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
| 2023 |
-
"dev": true,
|
| 2024 |
-
"license": "MIT",
|
| 2025 |
-
"dependencies": {
|
| 2026 |
-
"is-number": "^7.0.0"
|
| 2027 |
-
},
|
| 2028 |
-
"engines": {
|
| 2029 |
-
"node": ">=8.0"
|
| 2030 |
-
}
|
| 2031 |
-
},
|
| 2032 |
-
"node_modules/ts-interface-checker": {
|
| 2033 |
-
"version": "0.1.13",
|
| 2034 |
-
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
|
| 2035 |
-
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
|
| 2036 |
-
"dev": true,
|
| 2037 |
-
"license": "Apache-2.0"
|
| 2038 |
-
},
|
| 2039 |
-
"node_modules/tslib": {
|
| 2040 |
-
"version": "2.8.1",
|
| 2041 |
-
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
| 2042 |
-
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
| 2043 |
-
"license": "0BSD"
|
| 2044 |
-
},
|
| 2045 |
-
"node_modules/undici-types": {
|
| 2046 |
-
"version": "7.18.2",
|
| 2047 |
-
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
|
| 2048 |
-
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
|
| 2049 |
-
"license": "MIT"
|
| 2050 |
-
},
|
| 2051 |
-
"node_modules/update-browserslist-db": {
|
| 2052 |
-
"version": "1.2.3",
|
| 2053 |
-
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
|
| 2054 |
-
"integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
|
| 2055 |
-
"dev": true,
|
| 2056 |
-
"funding": [
|
| 2057 |
-
{
|
| 2058 |
-
"type": "opencollective",
|
| 2059 |
-
"url": "https://opencollective.com/browserslist"
|
| 2060 |
-
},
|
| 2061 |
-
{
|
| 2062 |
-
"type": "tidelift",
|
| 2063 |
-
"url": "https://tidelift.com/funding/github/npm/browserslist"
|
| 2064 |
-
},
|
| 2065 |
-
{
|
| 2066 |
-
"type": "github",
|
| 2067 |
-
"url": "https://github.com/sponsors/ai"
|
| 2068 |
-
}
|
| 2069 |
-
],
|
| 2070 |
-
"license": "MIT",
|
| 2071 |
-
"dependencies": {
|
| 2072 |
-
"escalade": "^3.2.0",
|
| 2073 |
-
"picocolors": "^1.1.1"
|
| 2074 |
-
},
|
| 2075 |
-
"bin": {
|
| 2076 |
-
"update-browserslist-db": "cli.js"
|
| 2077 |
-
},
|
| 2078 |
-
"peerDependencies": {
|
| 2079 |
-
"browserslist": ">= 4.21.0"
|
| 2080 |
-
}
|
| 2081 |
-
},
|
| 2082 |
-
"node_modules/util-deprecate": {
|
| 2083 |
-
"version": "1.0.2",
|
| 2084 |
-
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
| 2085 |
-
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
| 2086 |
-
"dev": true,
|
| 2087 |
-
"license": "MIT"
|
| 2088 |
-
},
|
| 2089 |
-
"node_modules/uuid": {
|
| 2090 |
-
"version": "9.0.1",
|
| 2091 |
-
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
| 2092 |
-
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
|
| 2093 |
-
"funding": [
|
| 2094 |
-
"https://github.com/sponsors/broofa",
|
| 2095 |
-
"https://github.com/sponsors/ctavan"
|
| 2096 |
-
],
|
| 2097 |
-
"license": "MIT",
|
| 2098 |
-
"bin": {
|
| 2099 |
-
"uuid": "dist/bin/uuid"
|
| 2100 |
-
}
|
| 2101 |
-
},
|
| 2102 |
-
"node_modules/wrappy": {
|
| 2103 |
-
"version": "1.0.2",
|
| 2104 |
-
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
| 2105 |
-
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
| 2106 |
-
"license": "ISC"
|
| 2107 |
-
},
|
| 2108 |
-
"node_modules/ws": {
|
| 2109 |
-
"version": "8.20.0",
|
| 2110 |
-
"resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz",
|
| 2111 |
-
"integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==",
|
| 2112 |
-
"license": "MIT",
|
| 2113 |
-
"engines": {
|
| 2114 |
-
"node": ">=10.0.0"
|
| 2115 |
-
},
|
| 2116 |
-
"peerDependencies": {
|
| 2117 |
-
"bufferutil": "^4.0.1",
|
| 2118 |
-
"utf-8-validate": ">=5.0.2"
|
| 2119 |
-
},
|
| 2120 |
-
"peerDependenciesMeta": {
|
| 2121 |
-
"bufferutil": {
|
| 2122 |
-
"optional": true
|
| 2123 |
-
},
|
| 2124 |
-
"utf-8-validate": {
|
| 2125 |
-
"optional": true
|
| 2126 |
-
}
|
| 2127 |
-
}
|
| 2128 |
-
}
|
| 2129 |
-
}
|
| 2130 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Downloads/hackathon/civicai/package.json
DELETED
|
@@ -1,28 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"name": "civicai",
|
| 3 |
-
"version": "0.1.0",
|
| 4 |
-
"private": true,
|
| 5 |
-
"scripts": {
|
| 6 |
-
"dev": "next dev",
|
| 7 |
-
"build": "next build",
|
| 8 |
-
"start": "next start"
|
| 9 |
-
},
|
| 10 |
-
"dependencies": {
|
| 11 |
-
"@sendgrid/mail": "^8.1.6",
|
| 12 |
-
"@supabase/supabase-js": "^2.100.1",
|
| 13 |
-
"chart.js": "^4.5.1",
|
| 14 |
-
"form-data": "^4.0.0",
|
| 15 |
-
"formidable": "^3.5.1",
|
| 16 |
-
"git": "^0.1.5",
|
| 17 |
-
"next": "^14.0.0",
|
| 18 |
-
"react": "^18.0.0",
|
| 19 |
-
"react-chartjs-2": "^5.3.1",
|
| 20 |
-
"react-dom": "^18.0.0",
|
| 21 |
-
"uuid": "^9.0.1"
|
| 22 |
-
},
|
| 23 |
-
"devDependencies": {
|
| 24 |
-
"autoprefixer": "^10.4.16",
|
| 25 |
-
"postcss": "^8.4.32",
|
| 26 |
-
"tailwindcss": "^3.4.0"
|
| 27 |
-
}
|
| 28 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Downloads/hackathon/civicai/pages/_app.jsx
DELETED
|
@@ -1,4 +0,0 @@
|
|
| 1 |
-
import '../styles/globals.css'
|
| 2 |
-
export default function App({ Component, pageProps }) {
|
| 3 |
-
return <Component {...pageProps} />
|
| 4 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Downloads/hackathon/civicai/pages/api/alert.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
| 1 |
-
import sgMail from '@sendgrid/mail'
|
| 2 |
-
sgMail.setApiKey(process.env.SENDGRID_API_KEY)
|
| 3 |
-
|
| 4 |
-
export default async function handler(req, res) {
|
| 5 |
-
if (req.method !== 'POST') return res.status(405).end()
|
| 6 |
-
const { complaint } = req.body
|
| 7 |
-
if (!complaint) return res.status(400).json({ error: 'No complaint data' })
|
| 8 |
-
|
| 9 |
-
const msg = {
|
| 10 |
-
to: process.env.ALERT_EMAIL,
|
| 11 |
-
from: 'citizencare-alerts@yourdomain.com',
|
| 12 |
-
subject: `[CRITICAL] Complaint Alert — ${complaint.department} Department`,
|
| 13 |
-
html: `
|
| 14 |
-
<div style="font-family:Arial,sans-serif;max-width:600px;margin:0 auto;">
|
| 15 |
-
<div style="background:#DC2626;color:white;padding:20px;border-radius:8px 8px 0 0;">
|
| 16 |
-
<h1 style="margin:0;font-size:20px;">🔴 Critical Complaint Alert</h1>
|
| 17 |
-
<p style="margin:4px 0 0;opacity:.9;font-size:14px;">CitizenCare Automated Alert</p>
|
| 18 |
-
</div>
|
| 19 |
-
<div style="background:#fff;border:1px solid #E5E7EB;border-top:none;padding:24px;border-radius:0 0 8px 8px;">
|
| 20 |
-
<table style="width:100%;border-collapse:collapse;font-size:14px;">
|
| 21 |
-
<tr style="border-bottom:1px solid #F3F4F6;">
|
| 22 |
-
<td style="padding:10px 0;color:#6B7280;width:160px;">Complaint ID</td>
|
| 23 |
-
<td style="padding:10px 0;font-family:monospace;">${complaint.id}</td>
|
| 24 |
-
</tr>
|
| 25 |
-
<tr style="border-bottom:1px solid #F3F4F6;">
|
| 26 |
-
<td style="padding:10px 0;color:#6B7280;">Department</td>
|
| 27 |
-
<td style="padding:10px 0;font-weight:bold;">${complaint.department}</td>
|
| 28 |
-
</tr>
|
| 29 |
-
<tr style="border-bottom:1px solid #F3F4F6;">
|
| 30 |
-
<td style="padding:10px 0;color:#6B7280;">Location</td>
|
| 31 |
-
<td style="padding:10px 0;">${complaint.location || 'Not specified'}</td>
|
| 32 |
-
</tr>
|
| 33 |
-
<tr>
|
| 34 |
-
<td style="padding:10px 0;color:#6B7280;">ETA</td>
|
| 35 |
-
<td style="padding:10px 0;">${complaint.estimated_resolution}</td>
|
| 36 |
-
</tr>
|
| 37 |
-
</table>
|
| 38 |
-
<div style="background:#FEF3C7;border-left:4px solid #F59E0B;padding:16px;margin:20px 0;border-radius:0 8px 8px 0;">
|
| 39 |
-
<p style="margin:0;color:#78350F;font-size:14px;">${complaint.summary}</p>
|
| 40 |
-
</div>
|
| 41 |
-
<ul style="margin:0;padding-left:20px;color:#374151;font-size:14px;line-height:2;">
|
| 42 |
-
${(complaint.action_items||[]).map(a=>`<li>${a}</li>`).join('')}
|
| 43 |
-
</ul>
|
| 44 |
-
<p style="margin-top:24px;font-size:12px;color:#9CA3AF;">
|
| 45 |
-
Logged at ${new Date().toLocaleString('en-IN',{timeZone:'Asia/Kolkata'})} IST
|
| 46 |
-
</p>
|
| 47 |
-
</div>
|
| 48 |
-
</div>`
|
| 49 |
-
}
|
| 50 |
-
try {
|
| 51 |
-
await sgMail.send(msg)
|
| 52 |
-
res.status(200).json({ sent: true })
|
| 53 |
-
} catch (err) {
|
| 54 |
-
res.status(500).json({ error: 'Alert failed', detail: err.message })
|
| 55 |
-
}
|
| 56 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Downloads/hackathon/civicai/pages/api/process.js
DELETED
|
@@ -1,530 +0,0 @@
|
|
| 1 |
-
export default async function handler(req, res) {
|
| 2 |
-
if (req.method !== 'POST') return res.status(405).end()
|
| 3 |
-
const { text, language } = req.body
|
| 4 |
-
if (!text) return res.status(400).json({ error: 'No complaint text provided' })
|
| 5 |
-
|
| 6 |
-
try {
|
| 7 |
-
// ─── STEP 1: DETECT LANGUAGE LOCALLY (NO API NEEDED) ─────────────────
|
| 8 |
-
// We detect the script from Unicode ranges and use the user-selected language.
|
| 9 |
-
// Multilingual keywords in Step 2 handle matching directly — no translation needed.
|
| 10 |
-
|
| 11 |
-
const detectScript = (t) => {
|
| 12 |
-
if (/[\u0900-\u097F]/.test(t)) return 'Hindi' // Devanagari (Hindi/Marathi)
|
| 13 |
-
if (/[\u0C00-\u0C7F]/.test(t)) return 'Telugu'
|
| 14 |
-
if (/[\u0B80-\u0BFF]/.test(t)) return 'Tamil'
|
| 15 |
-
if (/[\u0C80-\u0CFF]/.test(t)) return 'Kannada'
|
| 16 |
-
if (/[\u0980-\u09FF]/.test(t)) return 'Bengali'
|
| 17 |
-
if (/[\u0A80-\u0AFF]/.test(t)) return 'Gujarati'
|
| 18 |
-
if (/[\u0A00-\u0A7F]/.test(t)) return 'Punjabi'
|
| 19 |
-
if (/[\u0B00-\u0B7F]/.test(t)) return 'Odia'
|
| 20 |
-
return 'English'
|
| 21 |
-
}
|
| 22 |
-
|
| 23 |
-
let detectedLanguage = language || detectScript(text) || 'Unknown'
|
| 24 |
-
// If user selected a language, trust that; otherwise use script detection
|
| 25 |
-
if (!language || language === 'English') {
|
| 26 |
-
const scriptLang = detectScript(text)
|
| 27 |
-
if (scriptLang !== 'English') detectedLanguage = scriptLang
|
| 28 |
-
}
|
| 29 |
-
|
| 30 |
-
// Use original text directly for keyword matching — multilingual keywords cover all languages
|
| 31 |
-
const combinedText = text.toLowerCase()
|
| 32 |
-
|
| 33 |
-
// ─── STEP 2: MULTILINGUAL KEYWORD MAPS ──────────────────────────────
|
| 34 |
-
// Each department has keywords in English + Hindi + Telugu + Tamil + Kannada + Marathi + Bengali
|
| 35 |
-
|
| 36 |
-
const departmentKeywords = {
|
| 37 |
-
Hospital: [
|
| 38 |
-
// English
|
| 39 |
-
'hospital', 'doctor', 'nurse', 'patient', 'ward', 'emergency room', 'icu', 'medical staff',
|
| 40 |
-
'ambulance', 'surgery', 'operation theatre', 'blood bank', 'pharmacy', 'casualty',
|
| 41 |
-
// Hindi
|
| 42 |
-
'अस्पताल', 'डॉक्टर', 'नर्स', 'मरीज', 'एम्बुलेंस', 'ऑपरेशन', 'आईसीयू', 'फार्मेसी', 'खून',
|
| 43 |
-
// Telugu
|
| 44 |
-
'ఆసుపత్రి', 'డాక్టర్', 'నర్సు', 'రోగి', 'అంబులెన్స్', 'శస్త్రచికిత్స',
|
| 45 |
-
// Tamil
|
| 46 |
-
'மருத்துவமனை', 'மருத்துவர்', 'செவிலியர்', 'நோயாளி', 'அம்புலன்ஸ்',
|
| 47 |
-
// Kannada
|
| 48 |
-
'ಆಸ್ಪತ್ರೆ', 'ವೈದ್ಯ', 'ನರ್ಸ್', 'ರೋಗಿ', 'ಆಂಬುಲೆನ್ಸ್',
|
| 49 |
-
// Marathi
|
| 50 |
-
'रुग्णालय', 'डॉक्टर', 'परिचारिका', 'रुग्ण', 'रुग्णवाहिका',
|
| 51 |
-
// Bengali
|
| 52 |
-
'হাসপাতাল', 'ডাক্তার', 'নার্স', 'রোগী', 'অ্যাম্বুলেন্স'
|
| 53 |
-
],
|
| 54 |
-
Health: [
|
| 55 |
-
// English
|
| 56 |
-
'health', 'disease', 'medical', 'clinic', 'vaccination', 'public health', 'epidemic',
|
| 57 |
-
'infection', 'fever', 'dengue', 'malaria', 'cholera', 'food poisoning', 'contamination',
|
| 58 |
-
'hygiene', 'mental health', 'medicine', 'drug', 'pandemic', 'heart', 'cardiac', 'attack', 'chest pain', 'stroke',
|
| 59 |
-
// Hindi
|
| 60 |
-
'स्वास्थ्य', 'बीमारी', 'बुखार', 'डेंगू', 'मलेरिया', 'टीकाकरण', 'टीका', 'संक्रमण', 'चिकित्सा',
|
| 61 |
-
'दवाई', 'दवा', 'महामारी', 'खांसी', 'जुकाम', 'उल्टी', 'दस्त', 'विषाक्तता',
|
| 62 |
-
// Telugu
|
| 63 |
-
'ఆరోగ్యం', 'వ్యాధి', 'జ్వరం', 'డెంగ్యూ', 'మలేరియా', 'టీకా', 'అంటువ్యాధి', 'మందులు',
|
| 64 |
-
// Tamil
|
| 65 |
-
'சுகாதாரம்', 'நோய்', 'காய்ச்சல்', 'டெங்கு', 'மலேரியா', 'தடுப்பூசி', 'தொற்று', 'மருந்து',
|
| 66 |
-
// Kannada
|
| 67 |
-
'ಆರೋಗ್ಯ', 'ರೋಗ', 'ಜ್ವರ', 'ಡೆಂಗ್ಯೂ', 'ಮಲೇರಿಯಾ', 'ಲಸಿಕೆ', 'ಸೋಂಕು',
|
| 68 |
-
// Marathi
|
| 69 |
-
'आरोग्य', 'आजार', 'ताप', 'डेंग्यू', 'मलेरिया', 'लसीकरण', 'संसर्ग',
|
| 70 |
-
// Bengali
|
| 71 |
-
'স্বাস্থ্য', 'রোগ', 'জ্বর', 'ডেঙ্গু', 'ম্যালেরিয়া', 'টিকা', 'সংক্রমণ'
|
| 72 |
-
],
|
| 73 |
-
Police: [
|
| 74 |
-
// English
|
| 75 |
-
'police', 'theft', 'robbery', 'assault', 'crime', 'harassment', 'violence', 'murder',
|
| 76 |
-
'kidnapping', 'burglary', 'stalking', 'domestic violence', 'eve teasing', 'chain snatching',
|
| 77 |
-
'fraud', 'scam', 'cybercrime', 'extortion', 'threat', 'drunk driving', 'accident',
|
| 78 |
-
'FIR', 'stolen', 'missing person', 'drug trafficking', 'gambling', 'fighting',
|
| 79 |
-
// Hindi
|
| 80 |
-
'पुलिस', 'चोरी', 'लूट', 'डकैती', 'हमला', 'अपराध', 'उत्पीड़न', 'हत्या', 'हिंसा',
|
| 81 |
-
'अपहरण', 'धोखाधड़ी', 'छेड़छाड़', 'मारपीट', 'धमकी', 'चेन स्नैचिंग', 'नशा', 'शराब',
|
| 82 |
-
'गायब', 'लापता', 'गुंडागर्दी', 'एफआईआर',
|
| 83 |
-
// Telugu
|
| 84 |
-
'పోలీసు', 'దొంగతనం', 'దోపిడీ', 'దాడి', 'నేరం', 'వేధింపు', 'హత్య', 'హింస',
|
| 85 |
-
'అపహరణ', 'మోసం', 'బెదిరింపు', 'తాగి డ్రైవింగ్',
|
| 86 |
-
// Tamil
|
| 87 |
-
'காவல்', 'திருட்டு', 'கொள்ளை', 'தாக்குதல்', 'குற்றம்', 'தொல்லை', 'கொலை',
|
| 88 |
-
'கடத்தல்', 'மோசடி', 'மிரட்டல்', 'போலீஸ்',
|
| 89 |
-
// Kannada
|
| 90 |
-
'ಪೊಲೀಸ್', 'ಕಳ್ಳತನ', 'ದರೋಡೆ', 'ಹಲ್ಲೆ', 'ಅಪರಾಧ', 'ಕಿರುಕುಳ', 'ಕೊಲೆ',
|
| 91 |
-
'ಅಪಹರಣ', 'ವಂಚನೆ', 'ಬೆದರಿಕೆ',
|
| 92 |
-
// Marathi
|
| 93 |
-
'पोलीस', 'चोरी', 'दरोडा', 'हल्ला', 'गुन्हा', 'छळ', 'खून', 'अपहरण', 'फसवणूक',
|
| 94 |
-
// Bengali
|
| 95 |
-
'পুলিশ', 'চুরি', 'ডাকাতি', 'হামলা', 'অপরাধ', 'হয়রানি', 'খুন', 'অপহরণ', 'প্রতারণা'
|
| 96 |
-
],
|
| 97 |
-
Sanitation: [
|
| 98 |
-
// English
|
| 99 |
-
'garbage', 'trash', 'dustbin', 'sewage', 'drainage', 'smell', 'litter', 'sanitation',
|
| 100 |
-
'manhole', 'gutter', 'waste', 'dump', 'rubbish', 'compost', 'recycle', 'toilet',
|
| 101 |
-
'public toilet', 'open defecation', 'cleaning', 'sweeping', 'stinking', 'dirty',
|
| 102 |
-
'clogged drain', 'overflowing', 'mosquito breeding', 'filth', 'unhygienic',
|
| 103 |
-
// Hindi
|
| 104 |
-
'कचरा', 'कूड़ा', 'सफाई', 'नाली', 'गंदगी', 'बदबू', 'सीवर', 'मैनहोल', 'गटर',
|
| 105 |
-
'शौचालय', 'खुले में शौच', 'सड़ांध', 'गंदा', 'नालियाँ', 'डस्टबिन', 'मच्छर',
|
| 106 |
-
// Telugu
|
| 107 |
-
'చెత్త', 'మురుగు', 'పారిశుధ్యం', 'డ్రైనేజ్', 'వాసన', 'మురికి', 'మ్యాన్హోల్',
|
| 108 |
-
'శుభ్రత', 'మరుగుదొడ్డి', 'దుర్గంధం',
|
| 109 |
-
// Tamil
|
| 110 |
-
'குப்பை', 'கழிவு', 'சுகாதாரம்', 'வடிகால்', 'துர்நாற்றம்', 'கழிவுநீர்', 'கொசு',
|
| 111 |
-
'சுத்தம்', 'கழிப்பறை', 'அசுத்தம்',
|
| 112 |
-
// Kannada
|
| 113 |
-
'ಕಸ', 'ತ್ಯಾಜ್ಯ', 'ನೈರ್ಮಲ್ಯ', 'ಒಳಚರಂಡಿ', 'ದುರ್ವಾಸನೆ', 'ಗಟಾರ', 'ಶೌಚಾಲಯ',
|
| 114 |
-
// Marathi
|
| 115 |
-
'कचरा', 'सफाई', 'गटार', 'दुर्गंधी', 'मॅनहोल', 'शौचालय', 'स्वच्छता',
|
| 116 |
-
// Bengali
|
| 117 |
-
'আবর্জনা', 'জঞ্জাল', 'পরিষ্কার', 'নর্দমা', 'দুর্গন্ধ', 'ম্যানহোল', 'শৌচাগার'
|
| 118 |
-
],
|
| 119 |
-
Education: [
|
| 120 |
-
// English
|
| 121 |
-
'school', 'college', 'teacher', 'student', 'class', 'education', 'university',
|
| 122 |
-
'exam', 'syllabus', 'principal', 'hostel', 'library', 'scholarship', 'tuition',
|
| 123 |
-
'midday meal', 'playground', 'campus', 'classroom', 'lab', 'professor',
|
| 124 |
-
'admission', 'dropout', 'infrastructure', 'sports facility',
|
| 125 |
-
// Hindi
|
| 126 |
-
'स्कूल', 'विद्यालय', 'कॉलेज', 'शिक्षक', 'अध्यापक', 'छात्र', 'विद्यार्थी', 'शिक्षा',
|
| 127 |
-
'परीक्षा', 'पाठ्यक्रम', 'प्रधानाचार्य', 'पुस्तकालय', 'छात्रवृत्ति', 'मिड डे मील',
|
| 128 |
-
'कक्षा', 'प्रयोगशाला', 'खेल का मैदान', 'प्रवेश',
|
| 129 |
-
// Telugu
|
| 130 |
-
'పాఠశాల', 'కళాశాల', 'ఉపాధ్యాయుడు', 'విద్యార్థి', 'విద్య', 'పరీక్ష', 'ప్రధానోపాధ్యాయుడు',
|
| 131 |
-
'గ్రంథాలయం', 'ఉపకారవేతనం', 'మధ్యాహ్న భోజన��',
|
| 132 |
-
// Tamil
|
| 133 |
-
'பள்ளி', 'கல்லூரி', 'ஆசிரியர்', 'மாணவர்', 'கல்வி', 'தேர்வு', 'தலைமையாசிரியர்',
|
| 134 |
-
'நூலகம்', 'உதவித்தொகை', 'மதிய உணவு',
|
| 135 |
-
// Kannada
|
| 136 |
-
'ಶಾಲೆ', 'ಕಾಲೇಜು', 'ಶಿಕ್ಷಕ', 'ವಿದ್ಯಾರ್ಥಿ', 'ಶಿಕ್ಷಣ', 'ಪರೀಕ್ಷೆ', 'ಗ್ರಂಥಾಲಯ',
|
| 137 |
-
// Marathi
|
| 138 |
-
'शाळा', 'महाविद्यालय', 'शिक्षक', 'विद्यार्थी', 'शिक्षण', 'परीक्षा', 'ग्रंथालय',
|
| 139 |
-
// Bengali
|
| 140 |
-
'স্কুল', 'কলেজ', 'শিক্ষক', 'ছাত্র', 'শিক্ষা', 'পরীক্ষা', 'গ্রন্থাগার'
|
| 141 |
-
],
|
| 142 |
-
Roads: [
|
| 143 |
-
// English
|
| 144 |
-
'pothole', 'road', 'street', 'traffic', 'asphalt', 'bridge', 'roads', 'speedbreaker',
|
| 145 |
-
'speed breaker', 'zebra crossing', 'signal', 'traffic light', 'footpath', 'divider',
|
| 146 |
-
'highway', 'flyover', 'pavement', 'crack in road', 'uneven road', 'construction',
|
| 147 |
-
// Hindi
|
| 148 |
-
'गड्ढा', 'सड़क', 'रास्ता', 'ट्रैफिक', 'पुल', 'फ्लाईओवर', 'स्पीड ब्रेकर',
|
| 149 |
-
'ज़ेबरा क्रॉसिंग', 'सिग्नल', 'फुटपाथ', 'राजमार्ग', 'निर्माण',
|
| 150 |
-
// Telugu
|
| 151 |
-
'గుంత', 'రోడ్డు', 'రహదారి', 'ట్రాఫిక్', 'వంతెన', 'ఫ్లైఓవర్', 'సిగ్నల్', 'ఫుట్పాత్',
|
| 152 |
-
// Tamil
|
| 153 |
-
'குழி', 'சாலை', 'போக்குவரத்து', 'பாலம்', 'மேம்பாலம்', 'சிக்னல்', 'நடைபாதை',
|
| 154 |
-
// Kannada
|
| 155 |
-
'ಗುಂಡಿ', 'ರಸ್ತೆ', 'ಸಂಚಾರ', 'ಸೇತುವೆ', 'ಮೇಲ್ಸೇತುವೆ', 'ಸಿಗ್ನಲ್',
|
| 156 |
-
// Marathi
|
| 157 |
-
'खड्डा', 'रस्ता', 'वाहतूक', 'पूल', 'उड्डाणपूल', 'सिग्नल', 'पदपथ',
|
| 158 |
-
// Bengali
|
| 159 |
-
'গর্ত', 'রাস্তা', 'যানজট', 'সেতু', 'ফ্লাইওভার', 'সিগন্যাল', 'ফুটপাথ'
|
| 160 |
-
],
|
| 161 |
-
Water: [
|
| 162 |
-
// English
|
| 163 |
-
'water', 'leak', 'tap', 'pipeline', 'drinking water', 'flooding', 'water scarcity',
|
| 164 |
-
'borewell', 'water supply', 'contaminated water', 'water tank', 'water pressure',
|
| 165 |
-
'water logging', 'rain water', 'water connection', 'water bill', 'dirty water',
|
| 166 |
-
// Hindi
|
| 167 |
-
'पानी', 'नल', 'पाइपलाइन', 'जलापूर्ति', 'बोरवेल', 'बाढ़', 'जल', 'टंकी', 'रिसाव',
|
| 168 |
-
'पेयजल', 'गंदा पानी', 'पानी की कमी', 'जलभराव', 'पानी का बिल',
|
| 169 |
-
// Telugu
|
| 170 |
-
'నీరు', 'కొళాయి', 'పైపులైన్', 'తాగునీరు', 'బోరుబావి', 'వరదలు', 'నీటి ట్యాంక్',
|
| 171 |
-
// Tamil
|
| 172 |
-
'தண்ணீர்', 'குழாய்', 'குடிநீர்', 'ஆழ்துளை', 'வெள்ளம்', 'நீர் தொட்டி', 'நீர் வழங்கல்',
|
| 173 |
-
// Kannada
|
| 174 |
-
'ನೀರು', 'ನಲ್ಲಿ', 'ಕುಡಿಯುವ ನೀರು', 'ಕೊಳವೆಬಾವಿ', 'ಪ್ರವಾಹ', 'ನೀರಿನ ಟ್ಯಾಂಕ್',
|
| 175 |
-
// Marathi
|
| 176 |
-
'पाणी', 'नळ', 'पाइपलाइन', 'पिण्याचे पाणी', 'बोअरवेल', 'पूर', 'पाण्याची टाकी',
|
| 177 |
-
// Bengali
|
| 178 |
-
'জল', 'পানি', 'কল', 'পাইপলাইন', 'পানীয় জল', 'বন্যা', 'জলের ট্যাঙ্ক'
|
| 179 |
-
],
|
| 180 |
-
Electricity: [
|
| 181 |
-
// English
|
| 182 |
-
'power', 'electricity', 'outage', 'streetlight', 'transformer', 'voltage', 'breaker',
|
| 183 |
-
'power cut', 'short circuit', 'electric pole', 'wire', 'meter', 'electric shock',
|
| 184 |
-
'billing', 'power supply', 'generator', 'inverter', 'load shedding', 'blackout',
|
| 185 |
-
'broken streetlight', 'dark street', 'no light', 'lamps',
|
| 186 |
-
// Hindi
|
| 187 |
-
'बिजली', 'बत्ती', 'ट्रांसफार्मर', 'तार', 'स्ट्रीटलाइट', 'बिजली कटौती',
|
| 188 |
-
'शॉर्ट सर्किट', 'बिजली का खंभा', 'मीटर', 'बिजली का बिल', 'इन्वर्टर', 'अंधेरा',
|
| 189 |
-
// Telugu
|
| 190 |
-
'విద్యుత్', 'కరెంట్', 'ట్రాన్స్ఫార్మర్', 'వైర్', 'స్ట్రీట్ లైట్', 'పవర్ కట్',
|
| 191 |
-
'షార్ట్ సర్క్యూట్', 'మీటర్', 'చీకటి',
|
| 192 |
-
// Tamil
|
| 193 |
-
'மின்சாரம்', 'மின்கம்பி', 'மின்மாற்றி', 'தெரு விளக்கு', 'மின்தடை', 'மின்கட்டணம்',
|
| 194 |
-
'ஷார்ட் சர்க்யூட்', 'மீட்டர்', 'இருட்டு',
|
| 195 |
-
// Kannada
|
| 196 |
-
'ವಿದ್ಯುತ್', 'ಕರೆಂಟ್', 'ಟ್ರಾನ್ಸ್ಫಾರ್ಮರ್', 'ಬೀದಿ ದೀಪ', 'ವಿದ್ಯುತ್ ಕಡಿತ', 'ಮೀಟರ್',
|
| 197 |
-
// Marathi
|
| 198 |
-
'वीज', 'ट्रान्सफॉर्मर', 'पथदीप', 'वीज खंडित', 'शॉर्ट सर्किट', 'मीटर', 'अंधार',
|
| 199 |
-
// Bengali
|
| 200 |
-
'বিদ্যুৎ', 'ট্রান্সফর্মার', 'রাস্তার বাতি', 'লোডশেডিং', 'শর্ট সার্কিট', 'মিটার', 'অন্ধকার'
|
| 201 |
-
],
|
| 202 |
-
Rescue: [
|
| 203 |
-
// English
|
| 204 |
-
'rescue', 'fire brigade', 'firefighter', 'airlift', 'lifeguard', 'disaster response',
|
| 205 |
-
'natural disaster', 'search and rescue', 'fire', 'earthquake', 'cyclone', 'landslide',
|
| 206 |
-
'building collapse', 'flood rescue', 'trapped', 'drowning', 'explosion', 'gas leak',
|
| 207 |
-
// Hindi
|
| 208 |
-
'बचाव', 'आग', 'दमकल', 'भूकंप', 'तूफान', 'बाढ़ बचाव', 'फंसे', 'डूबना',
|
| 209 |
-
'विस्फोट', 'गैस लीक', 'इमारत गिरी', 'भूस्खलन', 'चक्रवात',
|
| 210 |
-
// Telugu
|
| 211 |
-
'రక్షణ', 'అగ్ని', 'భూకంపం', 'తుఫాను', 'చిక్కుకుపోయారు', 'మునిగిపోవడం',
|
| 212 |
-
'పేలుడు', 'గ్యాస్ లీక్', 'భవనం కూలిపోయింది',
|
| 213 |
-
// Tamil
|
| 214 |
-
'மீட்பு', 'தீ', 'நிலநடுக்கம்', 'புயல்', 'சிக்கியவர்', 'மூழ்கிய', 'வெடிப்பு',
|
| 215 |
-
'எரிவாயு கசிவு', 'கட்டிடம் இடிந்தது',
|
| 216 |
-
// Kannada
|
| 217 |
-
'ರಕ್ಷಣೆ', 'ಬೆಂಕಿ', 'ಭೂಕಂಪ', 'ಚಂಡಮಾರುತ', 'ಸಿಲುಕಿದ', 'ಮುಳುಗಿದ', 'ಸ್ಫೋಟ',
|
| 218 |
-
// Marathi
|
| 219 |
-
'बचाव', 'आग', 'भूकंप', 'वादळ', 'अडकले', 'बुडणे', 'स्फोट', 'गॅस गळती',
|
| 220 |
-
// Bengali
|
| 221 |
-
'উদ্ধার', 'আগুন', 'ভূমিকম্প', 'ঝড়', 'আটকে পড়া', 'ডুবে যাওয়া', 'বিস্ফোরণ', 'গ্যাস লিক'
|
| 222 |
-
],
|
| 223 |
-
Transport: [
|
| 224 |
-
// English
|
| 225 |
-
'bus', 'train', 'metro', 'auto', 'rickshaw', 'cab', 'taxi', 'public transport',
|
| 226 |
-
'bus stop', 'railway station', 'train delay', 'bus route', 'ticket', 'conductor',
|
| 227 |
-
'overcrowded', 'rash driving', 'traffic jam',
|
| 228 |
-
// Hindi
|
| 229 |
-
'बस', 'ट्रेन', 'मेट्रो', 'ऑटो', 'रिक्शा', 'टैक्सी', 'बस स्टॉप', 'रेलवे स्टेशन',
|
| 230 |
-
'ट्रेन लेट', 'भीड़भाड़', 'लापरवाह ड्राइविंग',
|
| 231 |
-
// Telugu
|
| 232 |
-
'బస్సు', 'రైలు', 'మెట్రో', 'ఆటో', 'రిక్షా', 'బస్ స్టాప్', 'రైల్వే స్టేషన్',
|
| 233 |
-
// Tamil
|
| 234 |
-
'பேருந்து', 'ரயில்', 'மெட்ரோ', 'ஆட்டோ', 'பேருந்து நிறுத்தம்', 'ரயில் நிலையம்',
|
| 235 |
-
// Kannada
|
| 236 |
-
'ಬಸ್', 'ರೈಲು', 'ಮೆಟ್ರೋ', 'ಆಟೋ', 'ಬಸ್ ನಿಲ್ದಾಣ', 'ರೈಲ್ವೇ ನಿಲ್ದಾಣ',
|
| 237 |
-
// Marathi
|
| 238 |
-
'बस', 'ट्रेन', 'मेट्रो', 'ऑटो', 'बस थांबा', 'रेल्वे स्टेशन',
|
| 239 |
-
// Bengali
|
| 240 |
-
'বাস', 'ট্রেন', 'মেট্রো', 'অটো', 'বাস স্টপ', 'রেলস্টেশন'
|
| 241 |
-
],
|
| 242 |
-
Municipal: [
|
| 243 |
-
// English
|
| 244 |
-
'property', 'building', 'construction', 'encroachment', 'illegal construction',
|
| 245 |
-
'parking', 'noise', 'stray dogs', 'stray animals', 'tax', 'birth certificate',
|
| 246 |
-
'death certificate', 'trade license', 'zoning', 'municipal', 'corporation',
|
| 247 |
-
'hawkers', 'street vendor', 'advertisement', 'hoarding',
|
| 248 |
-
// Hindi
|
| 249 |
-
'भवन', 'निर्माण', 'अतिक्रमण', 'अवैध निर्माण', 'पार्किंग', 'शोर', 'कुत्ते',
|
| 250 |
-
'आवारा जानवर', 'कर', 'जन्म प��रमाणपत्र', 'नगर निगम', 'नगरपालिका',
|
| 251 |
-
// Telugu
|
| 252 |
-
'భవనం', 'నిర్మాణం', 'ఆక్రమణ', 'పార్కింగ్', 'శబ్దం', 'వీధి కుక్కలు', 'పన్ను',
|
| 253 |
-
// Tamil
|
| 254 |
-
'கட்டிடம்', 'கட்டுமானம்', 'ஆக்கிரமிப்பு', 'பார்க்கிங்', 'சத்தம்', 'தெரு நாய்', 'வரி',
|
| 255 |
-
// Kannada
|
| 256 |
-
'ಕಟ್ಟಡ', 'ನಿರ್ಮಾಣ', 'ಅತಿಕ್ರಮಣ', 'ಪಾರ್ಕಿಂಗ್', 'ಶಬ್ದ', 'ಬೀದಿ ನಾಯಿ', 'ತೆರಿಗೆ',
|
| 257 |
-
// Marathi
|
| 258 |
-
'इमारत', 'बांधकाम', 'अतिक्रमण', 'पार्किंग', 'आवाज', 'भटके कुत्रे', 'कर',
|
| 259 |
-
// Bengali
|
| 260 |
-
'ভবন', 'নির্মাণ', 'দখল', 'পার্কিং', 'শব্দ', 'পথকুকুর', 'কর'
|
| 261 |
-
],
|
| 262 |
-
Environment: [
|
| 263 |
-
// English
|
| 264 |
-
'pollution', 'air quality', 'tree', 'deforestation', 'factory emission', 'smoke',
|
| 265 |
-
'dust', 'noise pollution', 'river pollution', 'lake', 'park', 'garden', 'green cover',
|
| 266 |
-
'plastic ban', 'waste burning', 'industrial waste', 'chemical',
|
| 267 |
-
// Hindi
|
| 268 |
-
'प्रदूषण', 'वायु प्रदूषण', 'पेड़', 'वनों की कटाई', 'धुआं', 'धूल', 'ध्वनि प्रदूषण',
|
| 269 |
-
'नदी प्रदूषण', 'झील', 'पार्क', 'बगीचा', 'प्लास्टिक', 'कचरा जलाना',
|
| 270 |
-
// Telugu
|
| 271 |
-
'కాలుష్యం', 'చెట్టు', 'పొగ', 'దుమ్ము', 'నది కాలుష్యం', 'పార్కు', 'ప్లాస్టిక్',
|
| 272 |
-
// Tamil
|
| 273 |
-
'மாசு', 'மரம்', 'புகை', 'தூசி', 'ஆற்று மாசு', 'பூங்கா', 'பிளாஸ்டிக்',
|
| 274 |
-
// Kannada
|
| 275 |
-
'ಮಾಲಿನ್ಯ', 'ಮರ', 'ಹೊಗೆ', 'ಧೂಳು', 'ನದಿ ಮಾಲಿನ್ಯ', 'ಉದ್ಯಾನ', 'ಪ್ಲಾಸ್ಟಿಕ್',
|
| 276 |
-
// Marathi
|
| 277 |
-
'प्रदूषण', 'झाड', 'धूर', 'धूळ', 'नदी प्रदूषण', 'उद्यान', 'प्लास्टिक',
|
| 278 |
-
// Bengali
|
| 279 |
-
'দূষণ', 'গাছ', 'ধোঁয়া', 'ধুলো', 'নদী দূষণ', 'পার্ক', 'প্লাস্টিক'
|
| 280 |
-
]
|
| 281 |
-
}
|
| 282 |
-
|
| 283 |
-
const urgencyKeywords = {
|
| 284 |
-
Critical: [
|
| 285 |
-
// English
|
| 286 |
-
'death', 'dying', 'dead', 'life threatening', 'life', 'injury', 'injured', 'fire',
|
| 287 |
-
'gas leak', 'explosion', 'drowning', 'crime in progress', 'shooting', 'murder',
|
| 288 |
-
'collapsed', 'heart attack', 'bleeding', 'unconscious', 'electrocuted', 'trapped',
|
| 289 |
-
// Hindi
|
| 290 |
-
'मौत', 'मरना', 'जान', 'खतरा', 'चोट', 'आग', 'गैस लीक', 'विस्फोट', 'डूबना',
|
| 291 |
-
'गोली', 'हत्या', 'दिल का दौरा', 'खून बह रहा', 'बेहोश', 'फंसे',
|
| 292 |
-
// Telugu
|
| 293 |
-
'మరణం', 'ప్రాణం', 'ప్రమాదం', 'గాయం', 'అగ్ని', 'పేలుడు', 'గుండెపోటు',
|
| 294 |
-
// Tamil
|
| 295 |
-
'மரணம்', 'உயிர்', 'ஆபத்து', 'காயம்', 'தீ', 'வெடிப்பு', 'மாரடைப்பு',
|
| 296 |
-
// Kannada
|
| 297 |
-
'ಸಾವು', 'ಜೀವ', 'ಅಪಾಯ', 'ಗಾಯ', 'ಬೆಂಕಿ', 'ಸ್ಫೋಟ',
|
| 298 |
-
// Bengali
|
| 299 |
-
'মৃত্যু', 'প্রাণ', 'বিপদ', 'আঘাত', 'আগুন', 'বিস্ফোরণ'
|
| 300 |
-
],
|
| 301 |
-
High: [
|
| 302 |
-
// English
|
| 303 |
-
'urgent', 'immediate', 'asap', 'emergency', 'danger', 'collapse', 'flood', 'blocked',
|
| 304 |
-
'severe', 'accident', 'broken', 'major', 'serious', 'critical condition', 'stranded',
|
| 305 |
-
// Hindi
|
| 306 |
-
'तत्काल', 'आपातकालीन', 'खतरनाक', 'गंभीर', 'टूटा', 'बाढ़', 'दुर्घटना', 'अवरुद्ध',
|
| 307 |
-
// Telugu
|
| 308 |
-
'అత్యవసరం', 'ప్రమాదకరం', 'తీవ్రమైన', 'విరిగింది', 'వరదలు', 'ప్రమాదం',
|
| 309 |
-
// Tamil
|
| 310 |
-
'அவசரம்', 'ஆபத்தான', 'தீவிர', 'உடைந்த', 'வெள்ளம்', 'விபத்து',
|
| 311 |
-
// Kannada
|
| 312 |
-
'ತುರ್ತು', 'ಅಪಾಯಕಾರಿ', 'ತೀವ್ರ', 'ಮುರಿದ', 'ಪ್ರವಾಹ', 'ಅಪಘಾತ',
|
| 313 |
-
// Bengali
|
| 314 |
-
'জরুরি', 'বিপজ্জনক', 'গুরুতর', 'ভাঙা', 'বন্যা', 'দুর্ঘটনা'
|
| 315 |
-
],
|
| 316 |
-
Medium: [
|
| 317 |
-
// English
|
| 318 |
-
'days', 'soon', 'need attention', 'problem persists', 'ongoing', 'continued',
|
| 319 |
-
'recurring', 'frequent', 'regular', 'multiple complaints', 'no response',
|
| 320 |
-
'not fixed', 'pending', 'weeks', 'several',
|
| 321 |
-
// Hindi
|
| 322 |
-
'कई दिन', 'जल्दी', 'ध्यान', 'समस्या बनी हुई', 'बार-बार', 'जवाब नहीं',
|
| 323 |
-
'ठीक नहीं', 'लंबित', 'हफ्ते',
|
| 324 |
-
// Telugu
|
| 325 |
-
'రోజులు', 'త్వరగా', 'సమస్య', 'పదేపదే', 'జవాబు లేదు',
|
| 326 |
-
// Tamil
|
| 327 |
-
'நாட்கள்', 'விரைவில்', 'பிரச்சனை', 'அடிக்கடி', 'பதில் இல்லை',
|
| 328 |
-
// Bengali
|
| 329 |
-
'দিন', 'শীঘ্র', 'সমস্যা', 'বারবার', 'উত্তর নেই'
|
| 330 |
-
],
|
| 331 |
-
Low: [
|
| 332 |
-
// English
|
| 333 |
-
'routine', 'minor', 'small', 'slow', 'inconvenience', 'suggestion', 'request',
|
| 334 |
-
'general', 'information', 'inquiry', 'feedback',
|
| 335 |
-
// Hindi
|
| 336 |
-
'छोटा', 'मामूली', 'सुझाव', 'जानकारी', 'अनुरोध', 'सामान्य',
|
| 337 |
-
// Telugu
|
| 338 |
-
'చిన్న', 'సూచన', 'సమాచారం', 'అభ్యర్థన',
|
| 339 |
-
// Tamil
|
| 340 |
-
'சிறிய', 'ஆலோசனை', 'தகவல்', 'கோரிக்கை',
|
| 341 |
-
// Bengali
|
| 342 |
-
'ছোট', 'সামান্য', 'পরামর্শ', 'তথ্য', 'অনুরোধ'
|
| 343 |
-
]
|
| 344 |
-
}
|
| 345 |
-
|
| 346 |
-
// ─── STEP 3: KEYWORD MATCHING ON COMBINED TEXT ──────────────────────
|
| 347 |
-
const scoreCategory = (keywordsMap, fallback) => {
|
| 348 |
-
const scores = {}
|
| 349 |
-
for (const [cat, keys] of Object.entries(keywordsMap)) {
|
| 350 |
-
for (const key of keys) {
|
| 351 |
-
if (combinedText.includes(key.toLowerCase())) {
|
| 352 |
-
scores[cat] = (scores[cat] || 0) + 1
|
| 353 |
-
}
|
| 354 |
-
}
|
| 355 |
-
}
|
| 356 |
-
const top = Object.entries(scores).sort((a, b) => b[1] - a[1])[0]
|
| 357 |
-
return top ? top[0] : fallback
|
| 358 |
-
}
|
| 359 |
-
|
| 360 |
-
let department = scoreCategory(departmentKeywords, 'Other')
|
| 361 |
-
let urgency = scoreCategory(urgencyKeywords, 'Low')
|
| 362 |
-
|
| 363 |
-
// Prefer Health for clear medical emergencies
|
| 364 |
-
if (/heart attack|cardiac arrest|chest pain|stroke|severe bleeding|medical emergency|unconscious|life-threatening/i.test(combinedText)) {
|
| 365 |
-
department = 'Health'
|
| 366 |
-
urgency = 'Critical'
|
| 367 |
-
}
|
| 368 |
-
|
| 369 |
-
// Urgency overrides
|
| 370 |
-
if (/accident|collapsed|severe|दुर्घटना|गंभीर/i.test(combinedText)) {
|
| 371 |
-
urgency = 'High'
|
| 372 |
-
}
|
| 373 |
-
|
| 374 |
-
if (department === 'Police' && /hit and run|killed|shooting|murder|हत्या|गोली|খুন|கொலை|ಕೊಲೆ/i.test(combinedText)) {
|
| 375 |
-
urgency = 'Critical'
|
| 376 |
-
}
|
| 377 |
-
if (department === 'Rescue') {
|
| 378 |
-
urgency = urgency === 'Low' ? 'High' : urgency
|
| 379 |
-
}
|
| 380 |
-
|
| 381 |
-
// ─── STEP 4: EXTRACT LOCATION ──────────────────────────────────────
|
| 382 |
-
const extractLocation = () => {
|
| 383 |
-
// Try English patterns
|
| 384 |
-
const enMatch = text.match(/(?:near|at|in|beside|outside|opposite)\s+([A-Za-z0-9\s',.-]{5,80})/i)
|
| 385 |
-
if (enMatch) return enMatch[1].trim()
|
| 386 |
-
|
| 387 |
-
// Try Hindi location patterns
|
| 388 |
-
const hiMatch = text.match(/(?:के पास|में|के सामने|के बगल में|पर)\s+(.{5,60})/i)
|
| 389 |
-
if (hiMatch) return hiMatch[1].trim()
|
| 390 |
-
|
| 391 |
-
// Try Telugu location patterns
|
| 392 |
-
const teMatch = text.match(/(?:దగ్గర|లో|వద్ద)\s+(.{5,60})/i)
|
| 393 |
-
if (teMatch) return teMatch[1].trim()
|
| 394 |
-
|
| 395 |
-
// Try Tamil location patterns
|
| 396 |
-
const taMatch = text.match(/(?:அருகில்|இல்|பக்கத்தில்)\s+(.{5,60})/i)
|
| 397 |
-
if (taMatch) return taMatch[1].trim()
|
| 398 |
-
|
| 399 |
-
// Fallback: look for common location words in any language
|
| 400 |
-
const spl = text.split(/\n|\.|,/)
|
| 401 |
-
return spl.find(s => /road|street|colony|area|block|sector|park|market|nagar|puram|pally|gali|chowk|rasta|marg|गली|चौक|मार्ग|నగర్|వీధి|தெரு|சாலை|রাস্তা/i.test(s))?.trim() || null
|
| 402 |
-
}
|
| 403 |
-
|
| 404 |
-
const location = extractLocation() || null
|
| 405 |
-
|
| 406 |
-
// ─── STEP 5: GENERATE SUMMARY ──────────────────────────────────────
|
| 407 |
-
const summary = (() => {
|
| 408 |
-
const core = text.split(/[\.?\!]\s*/).filter(Boolean).slice(0, 2).join('. ')
|
| 409 |
-
if (core.length < 20) return text.slice(0, 180)
|
| 410 |
-
return core.length > 200 ? `${core.slice(0, 197)}...` : core
|
| 411 |
-
})()
|
| 412 |
-
|
| 413 |
-
// ─── STEP 6: GENERATE ACTION ITEMS ─────────────────────────────────
|
| 414 |
-
const defaultActions = [
|
| 415 |
-
'Inspect the issue on site',
|
| 416 |
-
'Assign a responsible team',
|
| 417 |
-
'Provide status update to the resident'
|
| 418 |
-
]
|
| 419 |
-
|
| 420 |
-
const actionCandidates = []
|
| 421 |
-
|
| 422 |
-
if (department === 'Roads') {
|
| 423 |
-
actionCandidates.push('Repair or resurface the affected road stretch')
|
| 424 |
-
actionCandidates.push('Install warning signs and barricade the hazard')
|
| 425 |
-
}
|
| 426 |
-
if (department === 'Water') {
|
| 427 |
-
actionCandidates.push('Fix the water leakage and test supply pressure')
|
| 428 |
-
actionCandidates.push('Clear blockages in the pipeline and drain')
|
| 429 |
-
}
|
| 430 |
-
if (department === 'Sanitation') {
|
| 431 |
-
actionCandidates.push('Clean the garbage accumulation and service the drain')
|
| 432 |
-
actionCandidates.push('Schedule frequent waste collection for the area')
|
| 433 |
-
}
|
| 434 |
-
if (department === 'Electricity') {
|
| 435 |
-
actionCandidates.push('Inspect power infrastructure and repair fault')
|
| 436 |
-
actionCandidates.push('Restore electricity and replace defective fittings')
|
| 437 |
-
}
|
| 438 |
-
if (department === 'Health') {
|
| 439 |
-
actionCandidates.push('Arrange medical support and sanitation response')
|
| 440 |
-
actionCandidates.push('Deploy health inspection team to assess public health risk')
|
| 441 |
-
}
|
| 442 |
-
if (department === 'Hospital') {
|
| 443 |
-
actionCandidates.push('Dispatch medical team and ensure hospital bed availability')
|
| 444 |
-
actionCandidates.push('Coordinate with nearby hospitals for emergency care')
|
| 445 |
-
}
|
| 446 |
-
if (department === 'Rescue') {
|
| 447 |
-
actionCandidates.push('Mobilize rescue team and emergency services immediately')
|
| 448 |
-
actionCandidates.push('Coordinate evacuation and search-and-rescue operations')
|
| 449 |
-
}
|
| 450 |
-
if (department === 'Police') {
|
| 451 |
-
actionCandidates.push('Register the FIR and patrol the area immediately')
|
| 452 |
-
actionCandidates.push('Dispatch nearest patrol unit and collect evidence')
|
| 453 |
-
}
|
| 454 |
-
if (department === 'Education') {
|
| 455 |
-
actionCandidates.push('Notify the education officer and inspect the institution')
|
| 456 |
-
actionCandidates.push('Ensure compliance with educational standards and student safety')
|
| 457 |
-
}
|
| 458 |
-
if (department === 'Transport') {
|
| 459 |
-
actionCandidates.push('Inspect the transport service and take corrective action')
|
| 460 |
-
actionCandidates.push('Coordinate with the transport authority for route/schedule fixes')
|
| 461 |
-
}
|
| 462 |
-
if (department === 'Municipal') {
|
| 463 |
-
actionCandidates.push('Deploy municipal inspection team to verify the complaint')
|
| 464 |
-
actionCandidates.push('Issue notice if violation found and initiate corrective action')
|
| 465 |
-
}
|
| 466 |
-
if (department === 'Environment') {
|
| 467 |
-
actionCandidates.push('Conduct environmental survey and check pollution levels')
|
| 468 |
-
actionCandidates.push('Issue notice to violators and enforce environmental norms')
|
| 469 |
-
}
|
| 470 |
-
|
| 471 |
-
const action_items = [...new Set([...actionCandidates, ...defaultActions])].slice(0, 3)
|
| 472 |
-
|
| 473 |
-
// ─── STEP 7: RESOLUTION ETA ────────────────────────────────────────
|
| 474 |
-
const estimated_resolution = urgency === 'Critical' ? '12 hours'
|
| 475 |
-
: urgency === 'High' ? '24-48 hours'
|
| 476 |
-
: urgency === 'Medium' ? '3-5 days'
|
| 477 |
-
: '7-14 days'
|
| 478 |
-
|
| 479 |
-
const language_detected = detectedLanguage || language || 'Unknown'
|
| 480 |
-
|
| 481 |
-
const parsed = {
|
| 482 |
-
summary,
|
| 483 |
-
department,
|
| 484 |
-
urgency,
|
| 485 |
-
action_items,
|
| 486 |
-
location,
|
| 487 |
-
estimated_resolution,
|
| 488 |
-
language_detected
|
| 489 |
-
}
|
| 490 |
-
|
| 491 |
-
// ─── STEP 8: SAVE TO DATABASE ──────────────────────────────────────
|
| 492 |
-
const { supabase } = await import('../../lib/supabase')
|
| 493 |
-
const { data: saved, error } = await supabase
|
| 494 |
-
.from('complaints')
|
| 495 |
-
.insert({
|
| 496 |
-
raw_text: text,
|
| 497 |
-
language: language || 'Unknown',
|
| 498 |
-
summary: parsed.summary,
|
| 499 |
-
department: parsed.department,
|
| 500 |
-
urgency: parsed.urgency,
|
| 501 |
-
action_items: parsed.action_items,
|
| 502 |
-
location: parsed.location,
|
| 503 |
-
estimated_resolution: parsed.estimated_resolution,
|
| 504 |
-
language_detected: parsed.language_detected,
|
| 505 |
-
status: 'pending'
|
| 506 |
-
})
|
| 507 |
-
.select()
|
| 508 |
-
.single()
|
| 509 |
-
|
| 510 |
-
if (error) {
|
| 511 |
-
console.error('Supabase insert error:', JSON.stringify(error))
|
| 512 |
-
throw new Error(`Database error: ${error.message}`)
|
| 513 |
-
}
|
| 514 |
-
|
| 515 |
-
// ─── STEP 9: CRITICAL ALERT ────────────────────────────────────────
|
| 516 |
-
if (parsed.urgency === 'Critical') {
|
| 517 |
-
const base = process.env.NEXT_PUBLIC_BASE_URL || 'http://localhost:3000'
|
| 518 |
-
await fetch(`${base}/api/alert`, {
|
| 519 |
-
method: 'POST',
|
| 520 |
-
headers: { 'Content-Type': 'application/json' },
|
| 521 |
-
body: JSON.stringify({ complaint: saved })
|
| 522 |
-
}).catch(e => console.error('Alert failed:', e))
|
| 523 |
-
}
|
| 524 |
-
|
| 525 |
-
res.status(200).json(saved)
|
| 526 |
-
} catch (err) {
|
| 527 |
-
console.error('Processing error:', err)
|
| 528 |
-
res.status(500).json({ error: 'Processing failed', detail: err.message })
|
| 529 |
-
}
|
| 530 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Downloads/hackathon/civicai/pages/api/status.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
| 1 |
-
import { supabase } from '../../lib/supabase'
|
| 2 |
-
|
| 3 |
-
export default async function handler(req, res) {
|
| 4 |
-
if (req.method !== 'GET') return res.status(405).end()
|
| 5 |
-
const { id } = req.query
|
| 6 |
-
if (!id) return res.status(400).json({ error: 'Complaint ID required' })
|
| 7 |
-
const { data, error } = await supabase
|
| 8 |
-
.from('complaints')
|
| 9 |
-
.select('id,summary,department,urgency,status,estimated_resolution,created_at')
|
| 10 |
-
.eq('id', id)
|
| 11 |
-
.single()
|
| 12 |
-
if (error) return res.status(404).json({ error: 'Complaint not found' })
|
| 13 |
-
res.status(200).json(data)
|
| 14 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Downloads/hackathon/civicai/pages/api/transcribe.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
| 1 |
-
import formidable from 'formidable'
|
| 2 |
-
import fs from 'fs'
|
| 3 |
-
import os from 'os'
|
| 4 |
-
|
| 5 |
-
export const config = { api: { bodyParser: false } }
|
| 6 |
-
|
| 7 |
-
export default async function handler(req, res) {
|
| 8 |
-
if (req.method !== 'POST') return res.status(405).end()
|
| 9 |
-
|
| 10 |
-
const form = formidable({ uploadDir: os.tmpdir(), keepExtensions: true })
|
| 11 |
-
|
| 12 |
-
form.parse(req, async (err, fields, files) => {
|
| 13 |
-
if (err) return res.status(500).json({ error: 'File parse failed' })
|
| 14 |
-
try {
|
| 15 |
-
const audioFile = Array.isArray(files.audio) ? files.audio[0] : files.audio
|
| 16 |
-
if (!audioFile) return res.status(400).json({ error: 'No audio file received' })
|
| 17 |
-
|
| 18 |
-
// Read file as buffer (fixes stream incompatibility with native fetch)
|
| 19 |
-
const fileBuffer = fs.readFileSync(audioFile.filepath)
|
| 20 |
-
const fileName = audioFile.originalFilename || 'audio.webm'
|
| 21 |
-
const mimeType = audioFile.mimetype || 'audio/webm'
|
| 22 |
-
|
| 23 |
-
// Use Web FormData (native to Node 18+) instead of the npm form-data package
|
| 24 |
-
const formData = new FormData()
|
| 25 |
-
const blob = new Blob([fileBuffer], { type: mimeType })
|
| 26 |
-
formData.append('file', blob, fileName)
|
| 27 |
-
formData.append('model', 'whisper-1')
|
| 28 |
-
|
| 29 |
-
const apiKey = process.env.OPENAI_API_KEY
|
| 30 |
-
if (!apiKey) {
|
| 31 |
-
fs.unlink(audioFile.filepath, () => {})
|
| 32 |
-
return res.status(500).json({
|
| 33 |
-
error: 'No OpenAI API key configured',
|
| 34 |
-
useBrowserFallback: true
|
| 35 |
-
})
|
| 36 |
-
}
|
| 37 |
-
|
| 38 |
-
const response = await fetch('https://api.openai.com/v1/audio/transcriptions', {
|
| 39 |
-
method: 'POST',
|
| 40 |
-
headers: {
|
| 41 |
-
Authorization: `Bearer ${apiKey}`
|
| 42 |
-
},
|
| 43 |
-
body: formData
|
| 44 |
-
})
|
| 45 |
-
|
| 46 |
-
const data = await response.json()
|
| 47 |
-
fs.unlink(audioFile.filepath, () => {})
|
| 48 |
-
|
| 49 |
-
if (!response.ok) {
|
| 50 |
-
console.error('OpenAI Transcription error:', response.status, data)
|
| 51 |
-
return res.status(500).json({
|
| 52 |
-
error: 'Transcription service failed',
|
| 53 |
-
detail: data.error?.message || JSON.stringify(data),
|
| 54 |
-
useBrowserFallback: true
|
| 55 |
-
})
|
| 56 |
-
}
|
| 57 |
-
|
| 58 |
-
if (!data.text) throw new Error('No transcription text returned')
|
| 59 |
-
res.status(200).json({ text: data.text })
|
| 60 |
-
} catch (err) {
|
| 61 |
-
console.error('Transcription error:', err)
|
| 62 |
-
res.status(500).json({
|
| 63 |
-
error: 'Transcription failed',
|
| 64 |
-
detail: err.message,
|
| 65 |
-
useBrowserFallback: true
|
| 66 |
-
})
|
| 67 |
-
}
|
| 68 |
-
})
|
| 69 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Downloads/hackathon/civicai/pages/dashboard.jsx
DELETED
|
@@ -1,405 +0,0 @@
|
|
| 1 |
-
import { useEffect, useState } from 'react'
|
| 2 |
-
import { supabase } from '../lib/supabase'
|
| 3 |
-
import Link from 'next/link'
|
| 4 |
-
import { useRouter } from 'next/router'
|
| 5 |
-
import { Chart as ChartJS, CategoryScale, LinearScale, BarElement, ArcElement, Tooltip, Legend } from 'chart.js'
|
| 6 |
-
import { Bar, Doughnut } from 'react-chartjs-2'
|
| 7 |
-
|
| 8 |
-
ChartJS.register(CategoryScale, LinearScale, BarElement, ArcElement, Tooltip, Legend)
|
| 9 |
-
|
| 10 |
-
const URGENCY = {
|
| 11 |
-
Low: { hex: '#10b981', badge: 'bg-emerald-100 text-emerald-700', row: 'hover:bg-emerald-50/30' },
|
| 12 |
-
Medium: { hex: '#f59e0b', badge: 'bg-amber-100 text-amber-700', row: 'hover:bg-amber-50/30' },
|
| 13 |
-
High: { hex: '#f97316', badge: 'bg-orange-100 text-orange-700', row: 'hover:bg-orange-50/30' },
|
| 14 |
-
Critical: { hex: '#ef4444', badge: 'bg-red-100 text-red-700', row: 'hover:bg-red-50/30' }
|
| 15 |
-
}
|
| 16 |
-
|
| 17 |
-
const DEPT_COLORS = ['#6366f1','#8b5cf6','#06b6d4','#10b981','#f59e0b','#ef4444','#ec4899','#64748b','#22c55e','#f43f5e','#0ea5e9','#a855f7','#14b8a6']
|
| 18 |
-
const DEPT_ICONS = { Health:'🏥', Hospital:'🏨', Police:'🚔', Sanitation:'🗑️', Roads:'🛣️', Water:'💧', Electricity:'⚡', Education:'🎓', Rescue:'🚒', Transport:'🚌', Municipal:'🏛️', Environment:'🌿', Other:'📋' }
|
| 19 |
-
|
| 20 |
-
function StatCard({ label, value, color, sub }) {
|
| 21 |
-
return (
|
| 22 |
-
<div className="bg-white rounded-2xl border border-gray-200 p-5 shadow-sm">
|
| 23 |
-
<p className="text-xs font-medium text-gray-400 uppercase tracking-wide mb-2">{label}</p>
|
| 24 |
-
<p className={`text-3xl font-bold ${color}`}>{value}</p>
|
| 25 |
-
{sub && <p className="text-xs text-gray-400 mt-1">{sub}</p>}
|
| 26 |
-
</div>
|
| 27 |
-
)
|
| 28 |
-
}
|
| 29 |
-
|
| 30 |
-
export default function Dashboard() {
|
| 31 |
-
const [complaints, setComplaints] = useState([])
|
| 32 |
-
const [loading, setLoading] = useState(true)
|
| 33 |
-
const [user, setUser] = useState(null)
|
| 34 |
-
const [authLoading, setAuthLoading] = useState(true)
|
| 35 |
-
const [urgFilter, setUrgFilter] = useState('All')
|
| 36 |
-
const [deptFilter, setDeptFilter] = useState('All')
|
| 37 |
-
const [selected, setSelected] = useState(null)
|
| 38 |
-
const [search, setSearch] = useState('')
|
| 39 |
-
const router = useRouter()
|
| 40 |
-
|
| 41 |
-
useEffect(() => {
|
| 42 |
-
const checkAuth = async () => {
|
| 43 |
-
const { data: { session } } = await supabase.auth.getSession()
|
| 44 |
-
if (!session) {
|
| 45 |
-
router.push('/login')
|
| 46 |
-
return
|
| 47 |
-
}
|
| 48 |
-
setUser(session.user)
|
| 49 |
-
setAuthLoading(false)
|
| 50 |
-
}
|
| 51 |
-
checkAuth()
|
| 52 |
-
|
| 53 |
-
const { data: { subscription } } = supabase.auth.onAuthStateChange((event, session) => {
|
| 54 |
-
if (!session) {
|
| 55 |
-
router.push('/login')
|
| 56 |
-
} else {
|
| 57 |
-
setUser(session.user)
|
| 58 |
-
}
|
| 59 |
-
})
|
| 60 |
-
|
| 61 |
-
return () => subscription.unsubscribe()
|
| 62 |
-
}, [router])
|
| 63 |
-
|
| 64 |
-
useEffect(() => {
|
| 65 |
-
supabase.from('complaints').select('*').order('created_at', { ascending: false })
|
| 66 |
-
.then(({ data }) => { setComplaints(data || []); setLoading(false) })
|
| 67 |
-
|
| 68 |
-
const sub = supabase.channel('realtime-complaints')
|
| 69 |
-
.on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'complaints' },
|
| 70 |
-
p => setComplaints(prev => [p.new, ...prev]))
|
| 71 |
-
.subscribe()
|
| 72 |
-
return () => supabase.removeChannel(sub)
|
| 73 |
-
}, [])
|
| 74 |
-
|
| 75 |
-
const handleLogout = async () => {
|
| 76 |
-
await supabase.auth.signOut()
|
| 77 |
-
router.push('/login')
|
| 78 |
-
}
|
| 79 |
-
|
| 80 |
-
const departments = [...new Set(complaints.map(c => c.department).filter(Boolean))]
|
| 81 |
-
const urgencies = ['Low','Medium','High','Critical']
|
| 82 |
-
|
| 83 |
-
const filtered = complaints.filter(c => {
|
| 84 |
-
const u = urgFilter === 'All' || c.urgency === urgFilter
|
| 85 |
-
const d = deptFilter === 'All' || c.department === deptFilter
|
| 86 |
-
const s = !search || c.summary?.toLowerCase().includes(search.toLowerCase()) || c.location?.toLowerCase().includes(search.toLowerCase())
|
| 87 |
-
return u && d && s
|
| 88 |
-
})
|
| 89 |
-
|
| 90 |
-
const deptCounts = departments.map(d => complaints.filter(c => c.department === d).length)
|
| 91 |
-
const urgencyCounts = urgencies.map(u => complaints.filter(c => c.urgency === u).length)
|
| 92 |
-
|
| 93 |
-
const barData = {
|
| 94 |
-
labels: departments,
|
| 95 |
-
datasets: [{ label: 'Complaints', data: deptCounts, backgroundColor: DEPT_COLORS, borderRadius: 8, borderSkipped: false }]
|
| 96 |
-
}
|
| 97 |
-
const donutData = {
|
| 98 |
-
labels: urgencies,
|
| 99 |
-
datasets: [{ data: urgencyCounts, backgroundColor: urgencies.map(u => URGENCY[u].hex), borderWidth: 0, hoverOffset: 8 }]
|
| 100 |
-
}
|
| 101 |
-
const barOpts = {
|
| 102 |
-
responsive: true,
|
| 103 |
-
plugins: { legend: { display: false } },
|
| 104 |
-
scales: {
|
| 105 |
-
y: { beginAtZero: true, ticks: { stepSize: 1, color: '#9CA3AF' }, grid: { color: '#F3F4F6' }, border: { display: false } },
|
| 106 |
-
x: { ticks: { color: '#6B7280' }, grid: { display: false }, border: { display: false } }
|
| 107 |
-
}
|
| 108 |
-
}
|
| 109 |
-
|
| 110 |
-
return (
|
| 111 |
-
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-50">
|
| 112 |
-
|
| 113 |
-
{/* ── NAVBAR ───────────────────────────────────────────────────────────── */}
|
| 114 |
-
<nav className="bg-white border-b border-gray-200 sticky top-0 z-30">
|
| 115 |
-
<div className="max-w-7xl mx-auto px-6 h-14 flex items-center justify-between">
|
| 116 |
-
<div className="flex items-center gap-3">
|
| 117 |
-
<div className="w-8 h-8 bg-indigo-600 rounded-lg flex items-center justify-center">
|
| 118 |
-
<span className="text-white text-sm font-bold">C</span>
|
| 119 |
-
</div>
|
| 120 |
-
<div>
|
| 121 |
-
<span className="font-semibold text-gray-900 text-sm">CitizenCare</span>
|
| 122 |
-
<span className="text-gray-400 text-xs ml-2">Authority Dashboard</span>
|
| 123 |
-
</div>
|
| 124 |
-
</div>
|
| 125 |
-
<div className="flex items-center gap-3">
|
| 126 |
-
{complaints.some(c => c.urgency === 'Critical' && c.status === 'pending') && (
|
| 127 |
-
<span className="flex items-center gap-1.5 text-xs text-red-600 bg-red-50 border border-red-200 px-2.5 py-1 rounded-full font-medium animate-pulse">
|
| 128 |
-
<span className="w-1.5 h-1.5 bg-red-500 rounded-full"></span>
|
| 129 |
-
{complaints.filter(c => c.urgency === 'Critical' && c.status === 'pending').length} critical pending
|
| 130 |
-
</span>
|
| 131 |
-
)}
|
| 132 |
-
<span className="text-xs text-gray-500">{user?.email}</span>
|
| 133 |
-
<button
|
| 134 |
-
onClick={handleLogout}
|
| 135 |
-
className="text-xs font-medium text-gray-600 border border-gray-200 px-3 py-1.5 rounded-lg hover:bg-gray-50 transition-all"
|
| 136 |
-
>
|
| 137 |
-
Logout
|
| 138 |
-
</button>
|
| 139 |
-
<Link href="/" className="text-xs font-medium text-indigo-600 border border-indigo-200 px-3 py-1.5 rounded-lg hover:bg-indigo-50 transition-all">
|
| 140 |
-
← Citizen portal
|
| 141 |
-
</Link>
|
| 142 |
-
</div>
|
| 143 |
-
</div>
|
| 144 |
-
</nav>
|
| 145 |
-
|
| 146 |
-
<div className="max-w-7xl mx-auto px-6 py-6">
|
| 147 |
-
|
| 148 |
-
{authLoading ? (
|
| 149 |
-
<div className="flex items-center justify-center py-32 text-gray-300 text-sm gap-3">
|
| 150 |
-
<svg className="animate-spin w-5 h-5 text-indigo-400" fill="none" viewBox="0 0 24 24">
|
| 151 |
-
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"/>
|
| 152 |
-
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/>
|
| 153 |
-
</svg>
|
| 154 |
-
Checking authentication...
|
| 155 |
-
</div>
|
| 156 |
-
) : loading ? (
|
| 157 |
-
<div className="flex items-center justify-center py-32 text-gray-300 text-sm gap-3">
|
| 158 |
-
<svg className="animate-spin w-5 h-5 text-indigo-400" fill="none" viewBox="0 0 24 24">
|
| 159 |
-
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"/>
|
| 160 |
-
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/>
|
| 161 |
-
</svg>
|
| 162 |
-
Loading complaints...
|
| 163 |
-
</div>
|
| 164 |
-
) : (
|
| 165 |
-
<>
|
| 166 |
-
{/* ── STAT CARDS ─────────────────────────────────────────────────── */}
|
| 167 |
-
<div className="grid grid-cols-2 sm:grid-cols-4 gap-4 mb-6">
|
| 168 |
-
<StatCard label="Total" value={complaints.length} color="text-gray-900"
|
| 169 |
-
sub={`${complaints.filter(c=>c.status==='pending').length} pending`} />
|
| 170 |
-
<StatCard label="Critical" value={complaints.filter(c=>c.urgency==='Critical').length} color="text-red-600"
|
| 171 |
-
sub="Require immediate action" />
|
| 172 |
-
<StatCard label="Pending" value={complaints.filter(c=>c.status==='pending').length} color="text-amber-600"
|
| 173 |
-
sub="Awaiting resolution" />
|
| 174 |
-
<StatCard label="Resolved" value={complaints.filter(c=>c.status==='resolved').length} color="text-emerald-600"
|
| 175 |
-
sub={complaints.length ? `${Math.round(complaints.filter(c=>c.status==='resolved').length/complaints.length*100)}% resolution rate` : '0%'} />
|
| 176 |
-
</div>
|
| 177 |
-
|
| 178 |
-
{/* ── CHARTS ─────────────────────────────────────────────────────── */}
|
| 179 |
-
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4 mb-6">
|
| 180 |
-
<div className="lg:col-span-2 bg-white rounded-2xl border border-gray-200 p-5 shadow-sm">
|
| 181 |
-
<p className="text-sm font-semibold text-gray-700 mb-1">Complaints by department</p>
|
| 182 |
-
<p className="text-xs text-gray-400 mb-4">Total volume per government department</p>
|
| 183 |
-
{departments.length > 0 ? (
|
| 184 |
-
<Bar data={barData} options={barOpts} height={120} />
|
| 185 |
-
) : (
|
| 186 |
-
<div className="flex items-center justify-center h-36 text-gray-200 text-sm">No data yet — submit a complaint to see charts</div>
|
| 187 |
-
)}
|
| 188 |
-
</div>
|
| 189 |
-
|
| 190 |
-
<div className="bg-white rounded-2xl border border-gray-200 p-5 shadow-sm">
|
| 191 |
-
<p className="text-sm font-semibold text-gray-700 mb-1">Urgency breakdown</p>
|
| 192 |
-
<p className="text-xs text-gray-400 mb-4">Distribution of complaint severity</p>
|
| 193 |
-
{complaints.length > 0 ? (
|
| 194 |
-
<div className="space-y-3">
|
| 195 |
-
<Doughnut data={donutData} options={{ plugins: { legend: { display: false } }, cutout: '72%' }} />
|
| 196 |
-
<div className="space-y-2 mt-2">
|
| 197 |
-
{urgencies.map((u, i) => (
|
| 198 |
-
<div key={u} className="flex items-center justify-between text-sm">
|
| 199 |
-
<div className="flex items-center gap-2">
|
| 200 |
-
<span className="w-2.5 h-2.5 rounded-full" style={{ background: URGENCY[u].hex }}></span>
|
| 201 |
-
<span className="text-gray-600 text-xs">{u}</span>
|
| 202 |
-
</div>
|
| 203 |
-
<div className="flex items-center gap-2">
|
| 204 |
-
<div className="w-16 bg-gray-100 rounded-full h-1.5">
|
| 205 |
-
<div className="h-1.5 rounded-full transition-all" style={{
|
| 206 |
-
width: complaints.length ? `${urgencyCounts[i]/complaints.length*100}%` : '0%',
|
| 207 |
-
background: URGENCY[u].hex
|
| 208 |
-
}}/>
|
| 209 |
-
</div>
|
| 210 |
-
<span className="text-xs font-medium text-gray-700 w-4 text-right">{urgencyCounts[i]}</span>
|
| 211 |
-
</div>
|
| 212 |
-
</div>
|
| 213 |
-
))}
|
| 214 |
-
</div>
|
| 215 |
-
</div>
|
| 216 |
-
) : (
|
| 217 |
-
<div className="flex items-center justify-center h-36 text-gray-200 text-sm">No data yet</div>
|
| 218 |
-
)}
|
| 219 |
-
</div>
|
| 220 |
-
</div>
|
| 221 |
-
|
| 222 |
-
{/* ── TABLE ──────────────────────────────────────────────────────── */}
|
| 223 |
-
<div className="bg-white rounded-2xl border border-gray-200 shadow-sm overflow-hidden">
|
| 224 |
-
{/* Table toolbar */}
|
| 225 |
-
<div className="p-4 border-b border-gray-100 flex flex-wrap items-center gap-3">
|
| 226 |
-
<input value={search} onChange={e => setSearch(e.target.value)}
|
| 227 |
-
placeholder="Search complaints..."
|
| 228 |
-
className="border border-gray-200 rounded-lg px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-200 w-48 bg-gray-50 focus:bg-white transition-all"/>
|
| 229 |
-
|
| 230 |
-
<div className="flex gap-1.5 flex-wrap">
|
| 231 |
-
{['All',...urgencies].map(f => (
|
| 232 |
-
<button key={f} onClick={() => setUrgFilter(f)}
|
| 233 |
-
className={`px-3 py-1 rounded-full text-xs font-medium transition-all ${urgFilter === f ? 'bg-indigo-600 text-white' : 'bg-gray-100 text-gray-600 hover:bg-gray-200'}`}>
|
| 234 |
-
{f}
|
| 235 |
-
</button>
|
| 236 |
-
))}
|
| 237 |
-
</div>
|
| 238 |
-
|
| 239 |
-
<select value={deptFilter} onChange={e => setDeptFilter(e.target.value)}
|
| 240 |
-
className="text-xs border border-gray-200 rounded-lg px-2 py-1.5 text-gray-600 bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-200">
|
| 241 |
-
<option value="All">All departments</option>
|
| 242 |
-
{departments.map(d => <option key={d}>{d}</option>)}
|
| 243 |
-
</select>
|
| 244 |
-
|
| 245 |
-
<span className="ml-auto text-xs text-gray-400 font-medium">{filtered.length} of {complaints.length}</span>
|
| 246 |
-
</div>
|
| 247 |
-
|
| 248 |
-
<div className="overflow-x-auto">
|
| 249 |
-
<table className="w-full text-sm">
|
| 250 |
-
<thead>
|
| 251 |
-
<tr className="text-left text-xs font-semibold text-gray-400 bg-gray-50/80 border-b border-gray-100">
|
| 252 |
-
<th className="px-5 py-3">ID</th>
|
| 253 |
-
<th className="px-5 py-3">Summary</th>
|
| 254 |
-
<th className="px-5 py-3">Dept.</th>
|
| 255 |
-
<th className="px-5 py-3">Urgency</th>
|
| 256 |
-
<th className="px-5 py-3">ETA</th>
|
| 257 |
-
<th className="px-5 py-3">Status</th>
|
| 258 |
-
<th className="px-5 py-3">Action</th>
|
| 259 |
-
</tr>
|
| 260 |
-
</thead>
|
| 261 |
-
<tbody>
|
| 262 |
-
{filtered.length === 0 ? (
|
| 263 |
-
<tr><td colSpan={7} className="text-center py-16 text-gray-200 text-sm">No complaints found</td></tr>
|
| 264 |
-
) : filtered.map(c => (
|
| 265 |
-
<tr key={c.id}
|
| 266 |
-
className={`border-b border-gray-50 cursor-pointer transition-colors ${URGENCY[c.urgency]?.row || 'hover:bg-gray-50'}`}
|
| 267 |
-
onClick={() => setSelected(c)}>
|
| 268 |
-
<td className="px-5 py-3.5 font-mono text-xs text-gray-400">{c.id?.slice(0,8)}</td>
|
| 269 |
-
<td className="px-5 py-3.5 max-w-xs">
|
| 270 |
-
<p className="text-gray-700 truncate text-sm">{c.summary}</p>
|
| 271 |
-
{c.location && <p className="text-xs text-gray-400 mt-0.5 truncate">{c.location}</p>}
|
| 272 |
-
</td>
|
| 273 |
-
<td className="px-5 py-3.5 whitespace-nowrap text-gray-600 text-sm">
|
| 274 |
-
{DEPT_ICONS[c.department]||'📋'} {c.department}
|
| 275 |
-
</td>
|
| 276 |
-
<td className="px-5 py-3.5 whitespace-nowrap">
|
| 277 |
-
<span className={`text-xs font-semibold px-2.5 py-1 rounded-full ${URGENCY[c.urgency]?.badge || 'bg-gray-100 text-gray-600'}`}>
|
| 278 |
-
{c.urgency}
|
| 279 |
-
</span>
|
| 280 |
-
</td>
|
| 281 |
-
<td className="px-5 py-3.5 text-gray-500 text-xs whitespace-nowrap">{c.estimated_resolution}</td>
|
| 282 |
-
<td className="px-5 py-3.5">
|
| 283 |
-
<span className={`text-xs font-medium flex items-center gap-1.5 ${c.status === 'resolved' ? 'text-emerald-600' : 'text-amber-600'}`}>
|
| 284 |
-
<span className={`w-1.5 h-1.5 rounded-full ${c.status === 'resolved' ? 'bg-emerald-500' : 'bg-amber-400'}`}></span>
|
| 285 |
-
{c.status === 'resolved' ? 'Resolved' : 'Pending'}
|
| 286 |
-
</span>
|
| 287 |
-
</td>
|
| 288 |
-
<td className="px-5 py-3.5 whitespace-nowrap" onClick={e => e.stopPropagation()}>
|
| 289 |
-
{c.status !== 'resolved' ? (
|
| 290 |
-
<button onClick={() => updateStatus(c.id, 'resolved')}
|
| 291 |
-
className="text-xs text-emerald-600 border border-emerald-200 px-2.5 py-1.5 rounded-lg hover:bg-emerald-50 transition-all font-medium">
|
| 292 |
-
Resolve
|
| 293 |
-
</button>
|
| 294 |
-
) : (
|
| 295 |
-
<button onClick={() => updateStatus(c.id, 'pending')}
|
| 296 |
-
className="text-xs text-gray-400 border border-gray-200 px-2.5 py-1.5 rounded-lg hover:bg-gray-50 transition-all">
|
| 297 |
-
Reopen
|
| 298 |
-
</button>
|
| 299 |
-
)}
|
| 300 |
-
</td>
|
| 301 |
-
</tr>
|
| 302 |
-
))}
|
| 303 |
-
</tbody>
|
| 304 |
-
</table>
|
| 305 |
-
</div>
|
| 306 |
-
</div>
|
| 307 |
-
</>
|
| 308 |
-
)}
|
| 309 |
-
</div>
|
| 310 |
-
|
| 311 |
-
{/* ── DETAIL DRAWER ────────────────────────────────────────────────────── */}
|
| 312 |
-
{selected && (
|
| 313 |
-
<div className="fixed inset-0 z-40 flex justify-end animate-fade-in"
|
| 314 |
-
style={{ background: 'rgba(0,0,0,0.25)' }}
|
| 315 |
-
onClick={() => setSelected(null)}>
|
| 316 |
-
<div className="w-full max-w-md bg-white h-full overflow-y-auto shadow-2xl animate-slide-up"
|
| 317 |
-
onClick={e => e.stopPropagation()}>
|
| 318 |
-
<div className="p-6 space-y-5">
|
| 319 |
-
{/* Drawer header */}
|
| 320 |
-
<div className="flex items-start justify-between">
|
| 321 |
-
<div>
|
| 322 |
-
<p className="font-mono text-xs text-gray-400 mb-2 break-all">{selected.id}</p>
|
| 323 |
-
<span className={`text-xs font-semibold px-2.5 py-1 rounded-full ${URGENCY[selected.urgency]?.badge}`}>
|
| 324 |
-
{selected.urgency} priority
|
| 325 |
-
</span>
|
| 326 |
-
</div>
|
| 327 |
-
<button onClick={() => setSelected(null)}
|
| 328 |
-
className="w-8 h-8 flex items-center justify-center rounded-full hover:bg-gray-100 text-gray-400 hover:text-gray-600 transition-all text-xl leading-none">
|
| 329 |
-
×
|
| 330 |
-
</button>
|
| 331 |
-
</div>
|
| 332 |
-
|
| 333 |
-
{/* Dept + date */}
|
| 334 |
-
<div className="flex items-center justify-between text-sm">
|
| 335 |
-
<span className="font-medium text-gray-700">
|
| 336 |
-
{DEPT_ICONS[selected.department]||'📋'} {selected.department}
|
| 337 |
-
</span>
|
| 338 |
-
<span className="text-xs text-gray-400">{new Date(selected.created_at).toLocaleString('en-IN')}</span>
|
| 339 |
-
</div>
|
| 340 |
-
|
| 341 |
-
{/* Summary */}
|
| 342 |
-
<div className={`rounded-xl p-4 ${URGENCY[selected.urgency]?.badge?.includes('red') ? 'bg-red-50' : URGENCY[selected.urgency]?.badge?.includes('orange') ? 'bg-orange-50' : URGENCY[selected.urgency]?.badge?.includes('amber') ? 'bg-amber-50' : 'bg-emerald-50'}`}>
|
| 343 |
-
<p className="text-xs font-semibold text-gray-500 uppercase tracking-wide mb-2">AI Summary</p>
|
| 344 |
-
<p className="text-sm text-gray-700 leading-relaxed">{selected.summary}</p>
|
| 345 |
-
</div>
|
| 346 |
-
|
| 347 |
-
{/* Meta */}
|
| 348 |
-
<div className="grid grid-cols-2 gap-3">
|
| 349 |
-
{[
|
| 350 |
-
{ label: 'ETA', value: selected.estimated_resolution },
|
| 351 |
-
{ label: 'Language', value: selected.language_detected },
|
| 352 |
-
{ label: 'Location', value: selected.location || 'Not specified' },
|
| 353 |
-
{ label: 'Status', value: selected.status === 'resolved' ? 'Resolved ✓' : 'Pending...' }
|
| 354 |
-
].map(item => (
|
| 355 |
-
<div key={item.label} className="bg-gray-50 rounded-xl p-3">
|
| 356 |
-
<p className="text-xs text-gray-400 mb-1">{item.label}</p>
|
| 357 |
-
<p className="text-sm font-medium text-gray-800">{item.value}</p>
|
| 358 |
-
</div>
|
| 359 |
-
))}
|
| 360 |
-
</div>
|
| 361 |
-
|
| 362 |
-
{/* Action items */}
|
| 363 |
-
<div>
|
| 364 |
-
<p className="text-xs font-semibold text-gray-500 uppercase tracking-wide mb-3">Action items</p>
|
| 365 |
-
<div className="space-y-2">
|
| 366 |
-
{selected.action_items?.map((a, i) => (
|
| 367 |
-
<div key={i} className="flex items-start gap-3 p-3 bg-indigo-50 border border-indigo-100 rounded-xl">
|
| 368 |
-
<span className="w-5 h-5 bg-indigo-600 text-white text-xs rounded-full flex items-center justify-center flex-shrink-0 mt-0.5 font-semibold">{i+1}</span>
|
| 369 |
-
<span className="text-sm text-indigo-900">{a}</span>
|
| 370 |
-
</div>
|
| 371 |
-
))}
|
| 372 |
-
</div>
|
| 373 |
-
</div>
|
| 374 |
-
|
| 375 |
-
{/* Raw complaint */}
|
| 376 |
-
{selected.raw_text && (
|
| 377 |
-
<details className="bg-gray-50 rounded-xl overflow-hidden">
|
| 378 |
-
<summary className="px-4 py-3 text-xs text-gray-500 cursor-pointer font-medium hover:bg-gray-100 transition-all">
|
| 379 |
-
View original complaint text
|
| 380 |
-
</summary>
|
| 381 |
-
<p className="px-4 pb-4 text-xs text-gray-600 leading-relaxed">{selected.raw_text}</p>
|
| 382 |
-
</details>
|
| 383 |
-
)}
|
| 384 |
-
|
| 385 |
-
{/* Status buttons */}
|
| 386 |
-
<div className="pt-2 border-t border-gray-100">
|
| 387 |
-
<p className="text-xs text-gray-400 mb-3 font-medium">Update status</p>
|
| 388 |
-
<div className="flex gap-3">
|
| 389 |
-
<button onClick={() => updateStatus(selected.id, 'resolved')}
|
| 390 |
-
className="flex-1 py-2.5 text-sm font-semibold text-emerald-600 border border-emerald-200 rounded-xl hover:bg-emerald-50 transition-all">
|
| 391 |
-
Mark resolved
|
| 392 |
-
</button>
|
| 393 |
-
<button onClick={() => updateStatus(selected.id, 'pending')}
|
| 394 |
-
className="flex-1 py-2.5 text-sm font-medium text-amber-600 border border-amber-200 rounded-xl hover:bg-amber-50 transition-all">
|
| 395 |
-
Mark pending
|
| 396 |
-
</button>
|
| 397 |
-
</div>
|
| 398 |
-
</div>
|
| 399 |
-
</div>
|
| 400 |
-
</div>
|
| 401 |
-
</div>
|
| 402 |
-
)}
|
| 403 |
-
</div>
|
| 404 |
-
)
|
| 405 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Downloads/hackathon/civicai/pages/index.jsx
DELETED
|
@@ -1,568 +0,0 @@
|
|
| 1 |
-
import { useState, useRef } from 'react'
|
| 2 |
-
import Link from 'next/link'
|
| 3 |
-
|
| 4 |
-
const LANGUAGES = ['English','Hindi','Telugu','Tamil','Kannada','Marathi','Bengali','Gujarati','Punjabi','Odia']
|
| 5 |
-
|
| 6 |
-
const DEPT_ICONS = {
|
| 7 |
-
Health: '🏥', Hospital: '🏨', Police: '🚔', Sanitation: '🗑️', Roads: '🛣️',
|
| 8 |
-
Water: '💧', Electricity: '⚡', Education: '🎓', Rescue: '🚒',
|
| 9 |
-
Transport: '🚌', Municipal: '🏛️', Environment: '🌿', Other: '📋'
|
| 10 |
-
}
|
| 11 |
-
|
| 12 |
-
const URGENCY_CONFIG = {
|
| 13 |
-
Low: { bar: 'bg-emerald-500', bg: 'bg-emerald-50', border: 'border-emerald-200', text: 'text-emerald-700', badge: 'bg-emerald-100 text-emerald-700', dot: 'bg-emerald-400', label: 'Low Priority' },
|
| 14 |
-
Medium: { bar: 'bg-amber-500', bg: 'bg-amber-50', border: 'border-amber-200', text: 'text-amber-700', badge: 'bg-amber-100 text-amber-700', dot: 'bg-amber-400', label: 'Medium Priority' },
|
| 15 |
-
High: { bar: 'bg-orange-500', bg: 'bg-orange-50', border: 'border-orange-200', text: 'text-orange-700', badge: 'bg-orange-100 text-orange-700', dot: 'bg-orange-400', label: 'High Priority' },
|
| 16 |
-
Critical: { bar: 'bg-red-500', bg: 'bg-red-50', border: 'border-red-200', text: 'text-red-700', badge: 'bg-red-100 text-red-700', dot: 'bg-red-500', label: 'Critical — Alert sent' }
|
| 17 |
-
}
|
| 18 |
-
|
| 19 |
-
function StepBadge({ n, active, done }) {
|
| 20 |
-
return (
|
| 21 |
-
<div className={`w-8 h-8 rounded-full flex items-center justify-center text-sm font-semibold transition-all
|
| 22 |
-
${done ? 'bg-indigo-600 text-white' : active ? 'bg-indigo-600 text-white ring-4 ring-indigo-100' : 'bg-gray-100 text-gray-400'}`}>
|
| 23 |
-
{done ? '✓' : n}
|
| 24 |
-
</div>
|
| 25 |
-
)
|
| 26 |
-
}
|
| 27 |
-
|
| 28 |
-
function Spinner() {
|
| 29 |
-
return (
|
| 30 |
-
<svg className="animate-spin w-4 h-4" fill="none" viewBox="0 0 24 24">
|
| 31 |
-
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"/>
|
| 32 |
-
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/>
|
| 33 |
-
</svg>
|
| 34 |
-
)
|
| 35 |
-
}
|
| 36 |
-
|
| 37 |
-
export default function CitizenPortal() {
|
| 38 |
-
const [activeTab, setActiveTab] = useState('submit')
|
| 39 |
-
const [text, setText] = useState('')
|
| 40 |
-
const [lang, setLang] = useState('English')
|
| 41 |
-
const [loading, setLoading] = useState(false)
|
| 42 |
-
const [result, setResult] = useState(null)
|
| 43 |
-
const [error, setError] = useState(null)
|
| 44 |
-
const [recording, setRecording] = useState(false)
|
| 45 |
-
const [transcribing, setTranscribing] = useState(false)
|
| 46 |
-
const [copied, setCopied] = useState(false)
|
| 47 |
-
const [trackId, setTrackId] = useState('')
|
| 48 |
-
const [trackResult, setTrackResult] = useState(null)
|
| 49 |
-
const [trackLoading, setTrackLoading] = useState(false)
|
| 50 |
-
const mediaRef = useRef(null)
|
| 51 |
-
const chunksRef = useRef([])
|
| 52 |
-
const resultRef = useRef(null)
|
| 53 |
-
const speechRef = useRef(null)
|
| 54 |
-
|
| 55 |
-
// ── LANGUAGE CODE MAP for Web Speech API ──
|
| 56 |
-
const LANG_CODES = {
|
| 57 |
-
English: 'en-IN', Hindi: 'hi-IN', Telugu: 'te-IN', Tamil: 'ta-IN',
|
| 58 |
-
Kannada: 'kn-IN', Marathi: 'mr-IN', Bengali: 'bn-IN',
|
| 59 |
-
Gujarati: 'gu-IN', Punjabi: 'pa-IN', Odia: 'or-IN'
|
| 60 |
-
}
|
| 61 |
-
|
| 62 |
-
async function startRecording() {
|
| 63 |
-
setError(null)
|
| 64 |
-
|
| 65 |
-
// ── TRY 1: Browser Web Speech API (works offline, no credits needed) ──
|
| 66 |
-
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition
|
| 67 |
-
if (SpeechRecognition) {
|
| 68 |
-
try {
|
| 69 |
-
const recognition = new SpeechRecognition()
|
| 70 |
-
recognition.lang = LANG_CODES[lang] || 'en-IN'
|
| 71 |
-
recognition.interimResults = false
|
| 72 |
-
recognition.continuous = true
|
| 73 |
-
recognition.maxAlternatives = 1
|
| 74 |
-
|
| 75 |
-
let finalTranscript = ''
|
| 76 |
-
|
| 77 |
-
recognition.onresult = (event) => {
|
| 78 |
-
for (let i = event.resultIndex; i < event.results.length; i++) {
|
| 79 |
-
if (event.results[i].isFinal) {
|
| 80 |
-
finalTranscript += event.results[i][0].transcript + ' '
|
| 81 |
-
}
|
| 82 |
-
}
|
| 83 |
-
}
|
| 84 |
-
|
| 85 |
-
recognition.onerror = (event) => {
|
| 86 |
-
console.error('Speech recognition error:', event.error)
|
| 87 |
-
if (event.error === 'not-allowed') {
|
| 88 |
-
setError('Microphone access denied. Please allow microphone and try again.')
|
| 89 |
-
}
|
| 90 |
-
setRecording(false)
|
| 91 |
-
}
|
| 92 |
-
|
| 93 |
-
recognition.onend = () => {
|
| 94 |
-
if (finalTranscript.trim()) {
|
| 95 |
-
setText(prev => prev ? prev + ' ' + finalTranscript.trim() : finalTranscript.trim())
|
| 96 |
-
}
|
| 97 |
-
setRecording(false)
|
| 98 |
-
}
|
| 99 |
-
|
| 100 |
-
speechRef.current = recognition
|
| 101 |
-
recognition.start()
|
| 102 |
-
setRecording(true)
|
| 103 |
-
return
|
| 104 |
-
} catch (speechErr) {
|
| 105 |
-
console.error('Web Speech API failed, trying MediaRecorder fallback:', speechErr)
|
| 106 |
-
}
|
| 107 |
-
}
|
| 108 |
-
|
| 109 |
-
// ── TRY 2: MediaRecorder + OpenAI Whisper API fallback ──
|
| 110 |
-
try {
|
| 111 |
-
const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
|
| 112 |
-
mediaRef.current = new MediaRecorder(stream)
|
| 113 |
-
chunksRef.current = []
|
| 114 |
-
mediaRef.current.ondataavailable = e => chunksRef.current.push(e.data)
|
| 115 |
-
mediaRef.current.onstop = async () => {
|
| 116 |
-
setTranscribing(true)
|
| 117 |
-
try {
|
| 118 |
-
const blob = new Blob(chunksRef.current, { type: 'audio/webm' })
|
| 119 |
-
const fd = new FormData()
|
| 120 |
-
fd.append('audio', blob, 'complaint.webm')
|
| 121 |
-
const r = await fetch('/api/transcribe', { method: 'POST', body: fd })
|
| 122 |
-
const data = await r.json()
|
| 123 |
-
if (data.error) throw new Error(data.error)
|
| 124 |
-
setText(data.text)
|
| 125 |
-
} catch {
|
| 126 |
-
setError('Voice transcription failed. Please type your complaint instead.')
|
| 127 |
-
} finally {
|
| 128 |
-
setTranscribing(false)
|
| 129 |
-
}
|
| 130 |
-
stream.getTracks().forEach(t => t.stop())
|
| 131 |
-
}
|
| 132 |
-
mediaRef.current.start()
|
| 133 |
-
setRecording(true)
|
| 134 |
-
} catch {
|
| 135 |
-
setError('Microphone access denied. Please allow microphone and try again.')
|
| 136 |
-
}
|
| 137 |
-
}
|
| 138 |
-
|
| 139 |
-
function stopRecording() {
|
| 140 |
-
// Stop Web Speech API if active
|
| 141 |
-
if (speechRef.current) {
|
| 142 |
-
speechRef.current.stop()
|
| 143 |
-
speechRef.current = null
|
| 144 |
-
}
|
| 145 |
-
// Stop MediaRecorder if active
|
| 146 |
-
mediaRef.current?.stop()
|
| 147 |
-
setRecording(false)
|
| 148 |
-
}
|
| 149 |
-
|
| 150 |
-
async function submit() {
|
| 151 |
-
if (!text.trim()) return
|
| 152 |
-
setLoading(true)
|
| 153 |
-
setResult(null)
|
| 154 |
-
setError(null)
|
| 155 |
-
try {
|
| 156 |
-
const r = await fetch('/api/process', {
|
| 157 |
-
method: 'POST',
|
| 158 |
-
headers: { 'Content-Type': 'application/json' },
|
| 159 |
-
body: JSON.stringify({ text, language: lang })
|
| 160 |
-
})
|
| 161 |
-
const data = await r.json()
|
| 162 |
-
if (!r.ok) throw new Error(data.detail || data.error)
|
| 163 |
-
setResult(data)
|
| 164 |
-
setText('')
|
| 165 |
-
setTimeout(() => resultRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' }), 100)
|
| 166 |
-
} catch (err) {
|
| 167 |
-
setError(err.message || 'Something went wrong. Please try again.')
|
| 168 |
-
} finally {
|
| 169 |
-
setLoading(false)
|
| 170 |
-
}
|
| 171 |
-
}
|
| 172 |
-
|
| 173 |
-
async function trackComplaint() {
|
| 174 |
-
if (!trackId.trim()) return
|
| 175 |
-
setTrackLoading(true)
|
| 176 |
-
setTrackResult(null)
|
| 177 |
-
try {
|
| 178 |
-
const r = await fetch(`/api/status?id=${trackId.trim()}`)
|
| 179 |
-
const data = await r.json()
|
| 180 |
-
if (!r.ok) throw new Error('Not found')
|
| 181 |
-
setTrackResult(data)
|
| 182 |
-
} catch {
|
| 183 |
-
setTrackResult({ error: 'No complaint found with this ID. Please check and try again.' })
|
| 184 |
-
} finally {
|
| 185 |
-
setTrackLoading(false)
|
| 186 |
-
}
|
| 187 |
-
}
|
| 188 |
-
|
| 189 |
-
function copyId() {
|
| 190 |
-
if (result?.id) {
|
| 191 |
-
navigator.clipboard.writeText(result.id)
|
| 192 |
-
setCopied(true)
|
| 193 |
-
setTimeout(() => setCopied(false), 2000)
|
| 194 |
-
}
|
| 195 |
-
}
|
| 196 |
-
|
| 197 |
-
function getProgress(eta) {
|
| 198 |
-
if (eta.includes('12 hours')) return 90
|
| 199 |
-
if (eta.includes('24-48 hours')) return 70
|
| 200 |
-
if (eta.includes('3-5 days')) return 40
|
| 201 |
-
if (eta.includes('7-14 days')) return 20
|
| 202 |
-
return 50
|
| 203 |
-
}
|
| 204 |
-
|
| 205 |
-
const uc = result ? URGENCY_CONFIG[result.urgency] || URGENCY_CONFIG.Low : null
|
| 206 |
-
const charCount = text.length
|
| 207 |
-
const maxChars = 1000
|
| 208 |
-
|
| 209 |
-
return (
|
| 210 |
-
<div className="min-h-screen" style={{ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%)' }}>
|
| 211 |
-
|
| 212 |
-
{/* ── NAVBAR ─────────────────────────────────────────────────────────── */}
|
| 213 |
-
<nav className="bg-white/80 backdrop-blur border-b border-gray-200/60 sticky top-0 z-30">
|
| 214 |
-
<div className="max-w-4xl mx-auto px-4 h-14 flex items-center justify-between">
|
| 215 |
-
<div className="flex items-center gap-2.5">
|
| 216 |
-
<div className="w-8 h-8 bg-indigo-600 rounded-lg flex items-center justify-center">
|
| 217 |
-
<span className="text-white text-sm font-bold">C</span>
|
| 218 |
-
</div>
|
| 219 |
-
<div>
|
| 220 |
-
<span className="font-semibold text-gray-900 text-sm">CitizenCare</span>
|
| 221 |
-
<span className="text-gray-400 text-xs ml-2 hidden sm:inline">Citizen Grievance Portal</span>
|
| 222 |
-
</div>
|
| 223 |
-
</div>
|
| 224 |
-
<div className="flex items-center gap-3">
|
| 225 |
-
<Link href="/support"
|
| 226 |
-
className="text-xs font-medium text-indigo-600 border border-indigo-200 px-3 py-1.5 rounded-lg hover:bg-indigo-50 transition-all">
|
| 227 |
-
Help & Support
|
| 228 |
-
</Link>
|
| 229 |
-
<Link href="/dashboard"
|
| 230 |
-
className="text-xs font-medium text-indigo-600 border border-indigo-200 px-3 py-1.5 rounded-lg hover:bg-indigo-50 transition-all">
|
| 231 |
-
Authority Dashboard →
|
| 232 |
-
</Link>
|
| 233 |
-
</div>
|
| 234 |
-
</div>
|
| 235 |
-
</nav>
|
| 236 |
-
|
| 237 |
-
<div className="max-w-4xl mx-auto px-4 py-8">
|
| 238 |
-
|
| 239 |
-
{/* ── HERO ───────────────────────────────────────────────────────────── */}
|
| 240 |
-
<div className="text-center mb-8">
|
| 241 |
-
<div className="inline-flex items-center gap-2 bg-indigo-50 border border-indigo-200 text-indigo-700 text-xs font-medium px-3 py-1.5 rounded-full mb-4">
|
| 242 |
-
<span>Processed by local keyword parser</span>
|
| 243 |
-
<span className="w-1 h-1 bg-indigo-400 rounded-full"></span>
|
| 244 |
-
<span>Results in under 3 seconds</span>
|
| 245 |
-
</div>
|
| 246 |
-
<h1 className="text-3xl sm:text-4xl font-bold text-gray-900 mb-3 leading-tight">
|
| 247 |
-
Your complaint, <span className="text-indigo-600">heard instantly</span>
|
| 248 |
-
</h1>
|
| 249 |
-
<p className="text-gray-500 text-base max-w-xl mx-auto leading-relaxed">
|
| 250 |
-
Submit in any language — text or voice. Our AI converts it into a structured report and routes it to the right authority automatically.
|
| 251 |
-
</p>
|
| 252 |
-
</div>
|
| 253 |
-
|
| 254 |
-
{/* ── STAT PILLS ─────────────────────────────────────────────────────── */}
|
| 255 |
-
<div className="flex flex-wrap justify-center gap-3 mb-8">
|
| 256 |
-
{[
|
| 257 |
-
{ label: '13 departments', icon: '🏛️' },
|
| 258 |
-
{ label: '10+ languages', icon: '🌐' },
|
| 259 |
-
{ label: 'Voice + Text', icon: '🎙️' },
|
| 260 |
-
{ label: 'Instant alerts', icon: '🔔' }
|
| 261 |
-
].map(s => (
|
| 262 |
-
<div key={s.label} className="flex items-center gap-1.5 bg-white border border-gray-200 px-3 py-1.5 rounded-full text-sm text-gray-600 shadow-sm">
|
| 263 |
-
<span className="text-base" style={{fontSize:'14px'}}>{s.icon}</span>
|
| 264 |
-
<span>{s.label}</span>
|
| 265 |
-
</div>
|
| 266 |
-
))}
|
| 267 |
-
</div>
|
| 268 |
-
|
| 269 |
-
{/* ── TABS ───────────────────────────────────────────────────────────── */}
|
| 270 |
-
<div className="flex gap-1 bg-white border border-gray-200 p-1 rounded-xl mb-6 w-fit mx-auto shadow-sm">
|
| 271 |
-
{[
|
| 272 |
-
{ id: 'submit', label: 'Submit complaint' },
|
| 273 |
-
{ id: 'track', label: 'Track complaint' }
|
| 274 |
-
].map(tab => (
|
| 275 |
-
<button key={tab.id} onClick={() => { setActiveTab(tab.id); setError(null) }}
|
| 276 |
-
className={`px-5 py-2 rounded-lg text-sm font-medium transition-all ${
|
| 277 |
-
activeTab === tab.id
|
| 278 |
-
? 'bg-indigo-600 text-white shadow-sm'
|
| 279 |
-
: 'text-gray-500 hover:text-gray-700 hover:bg-gray-50'
|
| 280 |
-
}`}>
|
| 281 |
-
{tab.label}
|
| 282 |
-
</button>
|
| 283 |
-
))}
|
| 284 |
-
</div>
|
| 285 |
-
|
| 286 |
-
{/* ══════════════════════════════════════════════════════════════════════
|
| 287 |
-
SUBMIT TAB
|
| 288 |
-
══════════════════════════════════════════════════════════════════════ */}
|
| 289 |
-
{activeTab === 'submit' && (
|
| 290 |
-
<div className="space-y-4 animate-fade-in">
|
| 291 |
-
|
| 292 |
-
{/* Steps indicator */}
|
| 293 |
-
<div className="flex items-center justify-center gap-0 mb-6">
|
| 294 |
-
{['Write complaint','AI processes','Report generated'].map((label, i) => (
|
| 295 |
-
<div key={i} className="flex items-center">
|
| 296 |
-
<div className="flex flex-col items-center gap-1">
|
| 297 |
-
<StepBadge n={i+1} active={i===0 && !result} done={result && i < 2 || (result && i === 2)} />
|
| 298 |
-
<span className="text-xs text-gray-400 hidden sm:block">{label}</span>
|
| 299 |
-
</div>
|
| 300 |
-
{i < 2 && <div className={`w-12 sm:w-20 h-0.5 mx-2 mb-4 transition-all ${result ? 'bg-indigo-400' : 'bg-gray-200'}`}/>}
|
| 301 |
-
</div>
|
| 302 |
-
))}
|
| 303 |
-
</div>
|
| 304 |
-
|
| 305 |
-
{/* Main form card */}
|
| 306 |
-
<div className="bg-white rounded-2xl border border-gray-200 shadow-sm overflow-hidden">
|
| 307 |
-
{/* Card header */}
|
| 308 |
-
<div className="px-6 pt-5 pb-4 border-b border-gray-100">
|
| 309 |
-
<h2 className="font-semibold text-gray-800 text-base">Describe your complaint</h2>
|
| 310 |
-
<p className="text-xs text-gray-400 mt-0.5">Be as detailed as possible — include location, time, and what happened</p>
|
| 311 |
-
</div>
|
| 312 |
-
|
| 313 |
-
<div className="p-6 space-y-4">
|
| 314 |
-
{/* Language + Voice row */}
|
| 315 |
-
<div className="flex gap-3 flex-wrap">
|
| 316 |
-
<div className="flex items-center gap-2">
|
| 317 |
-
<label className="text-xs font-medium text-gray-500">Language</label>
|
| 318 |
-
<select value={lang} onChange={e => setLang(e.target.value)}
|
| 319 |
-
className="border border-gray-200 rounded-lg px-3 py-2 text-sm text-gray-700 bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-200 focus:bg-white transition-all">
|
| 320 |
-
{LANGUAGES.map(l => <option key={l}>{l}</option>)}
|
| 321 |
-
</select>
|
| 322 |
-
</div>
|
| 323 |
-
|
| 324 |
-
<button
|
| 325 |
-
onClick={recording ? stopRecording : startRecording}
|
| 326 |
-
disabled={transcribing}
|
| 327 |
-
className={`flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium border transition-all ${
|
| 328 |
-
recording ? 'bg-red-50 border-red-300 text-red-600 animate-pulse' :
|
| 329 |
-
transcribing ? 'bg-gray-50 border-gray-200 text-gray-400 cursor-wait' :
|
| 330 |
-
'bg-gray-50 border-gray-200 text-gray-600 hover:bg-indigo-50 hover:border-indigo-200 hover:text-indigo-600'
|
| 331 |
-
}`}>
|
| 332 |
-
{recording ? (
|
| 333 |
-
<><span className="w-2 h-2 bg-red-500 rounded-full pulse-dot"></span> Stop recording</>
|
| 334 |
-
) : transcribing ? (
|
| 335 |
-
<><Spinner /> Transcribing...</>
|
| 336 |
-
) : (
|
| 337 |
-
<><span className="text-base" style={{fontSize:'14px'}}>🎙️</span> Voice input</>
|
| 338 |
-
)}
|
| 339 |
-
</button>
|
| 340 |
-
</div>
|
| 341 |
-
|
| 342 |
-
{/* Textarea */}
|
| 343 |
-
<div className="relative">
|
| 344 |
-
<textarea
|
| 345 |
-
value={text}
|
| 346 |
-
onChange={e => setText(e.target.value.slice(0, maxChars))}
|
| 347 |
-
placeholder={`Write your complaint here in any language...\n\nExample: "There is a large pothole near Ramaiah School on MG Road. Two bikes fell last week. Nobody has fixed it in 3 weeks despite multiple calls."`}
|
| 348 |
-
className="w-full border border-gray-200 rounded-xl p-4 text-sm text-gray-800 resize-none focus:outline-none focus:ring-2 focus:ring-indigo-300 focus:border-indigo-300 placeholder-gray-300 transition-all bg-gray-50 focus:bg-white"
|
| 349 |
-
rows={6}
|
| 350 |
-
/>
|
| 351 |
-
<span className={`absolute bottom-3 right-3 text-xs ${charCount > maxChars * 0.9 ? 'text-orange-400' : 'text-gray-300'}`}>
|
| 352 |
-
{charCount}/{maxChars}
|
| 353 |
-
</span>
|
| 354 |
-
</div>
|
| 355 |
-
|
| 356 |
-
{/* Error */}
|
| 357 |
-
{error && (
|
| 358 |
-
<div className="flex items-start gap-2 p-3 bg-red-50 border border-red-200 rounded-xl text-sm text-red-600 animate-slide-up">
|
| 359 |
-
<span className="text-base mt-0.5" style={{fontSize:'14px'}}>⚠️</span>
|
| 360 |
-
{error}
|
| 361 |
-
</div>
|
| 362 |
-
)}
|
| 363 |
-
|
| 364 |
-
{/* Submit button */}
|
| 365 |
-
<button
|
| 366 |
-
onClick={submit}
|
| 367 |
-
disabled={loading || !text.trim() || transcribing}
|
| 368 |
-
className="w-full bg-indigo-600 text-white rounded-xl py-3.5 text-sm font-semibold hover:bg-indigo-700 active:scale-[.99] disabled:opacity-40 disabled:cursor-not-allowed transition-all flex items-center justify-center gap-2 shadow-sm">
|
| 369 |
-
{loading ? (
|
| 370 |
-
<><Spinner /> Processing your complaint...</>
|
| 371 |
-
) : (
|
| 372 |
-
<><span className="text-base" style={{fontSize:'14px'}}>📤</span> Submit complaint</>
|
| 373 |
-
)}
|
| 374 |
-
</button>
|
| 375 |
-
|
| 376 |
-
<p className="text-center text-xs text-gray-400">
|
| 377 |
-
Your complaint is processed using local keyword detection and routed to the best department within seconds.
|
| 378 |
-
</p>
|
| 379 |
-
</div>
|
| 380 |
-
</div>
|
| 381 |
-
|
| 382 |
-
{/* ── RESULT CARD ─────────────────────────────────────────────────── */}
|
| 383 |
-
{result && (
|
| 384 |
-
<div ref={resultRef} className={`bg-white rounded-2xl border-2 ${uc.border} shadow-sm overflow-hidden animate-slide-up`}>
|
| 385 |
-
|
| 386 |
-
{/* Urgency banner */}
|
| 387 |
-
<div className={`${uc.bar} px-6 py-3 flex items-center justify-between`}>
|
| 388 |
-
<div className="flex items-center gap-2">
|
| 389 |
-
<span className="text-white font-semibold text-sm">{uc.label}</span>
|
| 390 |
-
{result.urgency === 'Critical' && (
|
| 391 |
-
<span className="bg-white/20 text-white text-xs px-2 py-0.5 rounded-full">Alert sent to authority</span>
|
| 392 |
-
)}
|
| 393 |
-
</div>
|
| 394 |
-
<span className="text-white/80 text-xs">{result.department}</span>
|
| 395 |
-
</div>
|
| 396 |
-
|
| 397 |
-
<div className="p-6 space-y-5">
|
| 398 |
-
{/* ID row */}
|
| 399 |
-
<div className="flex items-center justify-between p-3 bg-gray-50 rounded-xl">
|
| 400 |
-
<div>
|
| 401 |
-
<p className="text-xs text-gray-400 mb-0.5">Your complaint ID — save this to track your complaint</p>
|
| 402 |
-
<p className="font-mono text-sm text-gray-700 font-medium">{result.id}</p>
|
| 403 |
-
</div>
|
| 404 |
-
<button onClick={copyId}
|
| 405 |
-
className="text-xs text-indigo-600 border border-indigo-200 px-3 py-1.5 rounded-lg hover:bg-indigo-50 transition-all flex items-center gap-1">
|
| 406 |
-
{copied ? '✓ Copied' : 'Copy ID'}
|
| 407 |
-
</button>
|
| 408 |
-
</div>
|
| 409 |
-
|
| 410 |
-
{/* Summary */}
|
| 411 |
-
<div className={`${uc.bg} rounded-xl p-4`}>
|
| 412 |
-
<p className="text-xs font-semibold text-gray-500 uppercase tracking-wide mb-2">AI Summary</p>
|
| 413 |
-
<p className="text-sm text-gray-700 leading-relaxed">{result.summary}</p>
|
| 414 |
-
</div>
|
| 415 |
-
|
| 416 |
-
{/* Meta grid */}
|
| 417 |
-
<div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
|
| 418 |
-
{[
|
| 419 |
-
{ label: 'Department', value: `${DEPT_ICONS[result.department] || '📋'} ${result.department}` },
|
| 420 |
-
{ label: 'Resolution ETA', value: result.estimated_resolution, progress: getProgress(result.estimated_resolution) },
|
| 421 |
-
{ label: 'Language', value: result.language_detected },
|
| 422 |
-
{ label: 'Location', value: result.location || 'Not specified' }
|
| 423 |
-
].map(item => (
|
| 424 |
-
<div key={item.label} className="bg-gray-50 rounded-xl p-3">
|
| 425 |
-
<p className="text-gray-400 text-xs mb-1">{item.label}</p>
|
| 426 |
-
<p className="text-gray-800 font-medium text-sm leading-tight">{item.value}</p>
|
| 427 |
-
{item.progress && (
|
| 428 |
-
<div className="mt-2 w-full bg-gray-200 rounded-full h-1.5">
|
| 429 |
-
<div
|
| 430 |
-
className="bg-indigo-600 h-1.5 rounded-full transition-all duration-500"
|
| 431 |
-
style={{ width: `${item.progress}%` }}
|
| 432 |
-
></div>
|
| 433 |
-
</div>
|
| 434 |
-
)}
|
| 435 |
-
</div>
|
| 436 |
-
))}
|
| 437 |
-
</div>
|
| 438 |
-
|
| 439 |
-
{/* Action items */}
|
| 440 |
-
<div>
|
| 441 |
-
<p className="text-xs font-semibold text-gray-500 uppercase tracking-wide mb-3">Action items for authority</p>
|
| 442 |
-
<div className="space-y-2">
|
| 443 |
-
{result.action_items?.map((a, i) => (
|
| 444 |
-
<div key={i} className="flex items-start gap-3 p-3 bg-indigo-50 border border-indigo-100 rounded-xl">
|
| 445 |
-
<span className="w-5 h-5 bg-indigo-600 text-white text-xs rounded-full flex items-center justify-center flex-shrink-0 mt-0.5 font-semibold">
|
| 446 |
-
{i + 1}
|
| 447 |
-
</span>
|
| 448 |
-
<span className="text-sm text-indigo-900">{a}</span>
|
| 449 |
-
</div>
|
| 450 |
-
))}
|
| 451 |
-
</div>
|
| 452 |
-
</div>
|
| 453 |
-
|
| 454 |
-
<div className="pt-3 border-t border-gray-100 flex items-center justify-between">
|
| 455 |
-
<p className="text-xs text-gray-400">
|
| 456 |
-
Submitted {new Date(result.created_at).toLocaleString('en-IN')}
|
| 457 |
-
</p>
|
| 458 |
-
<button
|
| 459 |
-
onClick={() => { setResult(null); setActiveTab('track'); setTrackId(result.id) }}
|
| 460 |
-
className="text-xs text-indigo-600 hover:underline">
|
| 461 |
-
Track this complaint →
|
| 462 |
-
</button>
|
| 463 |
-
</div>
|
| 464 |
-
</div>
|
| 465 |
-
</div>
|
| 466 |
-
)}
|
| 467 |
-
</div>
|
| 468 |
-
)}
|
| 469 |
-
|
| 470 |
-
{/* ══════════════════════════════════════════════════════════════════════
|
| 471 |
-
TRACK TAB
|
| 472 |
-
══════════════════════════════════════════════════════════════════════ */}
|
| 473 |
-
{activeTab === 'track' && (
|
| 474 |
-
<div className="animate-fade-in">
|
| 475 |
-
<div className="bg-white rounded-2xl border border-gray-200 shadow-sm overflow-hidden">
|
| 476 |
-
<div className="px-6 pt-5 pb-4 border-b border-gray-100">
|
| 477 |
-
<h2 className="font-semibold text-gray-800 text-base">Track your complaint</h2>
|
| 478 |
-
<p className="text-xs text-gray-400 mt-0.5">Enter the complaint ID you received when you submitted</p>
|
| 479 |
-
</div>
|
| 480 |
-
<div className="p-6 space-y-4">
|
| 481 |
-
<div className="flex gap-3">
|
| 482 |
-
<input
|
| 483 |
-
value={trackId}
|
| 484 |
-
onChange={e => setTrackId(e.target.value)}
|
| 485 |
-
placeholder="Paste your complaint ID here..."
|
| 486 |
-
className="flex-1 border border-gray-200 rounded-xl px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-200 bg-gray-50 focus:bg-white transition-all"
|
| 487 |
-
/>
|
| 488 |
-
<button onClick={trackComplaint} disabled={!trackId.trim() || trackLoading}
|
| 489 |
-
className="px-5 py-3 bg-indigo-600 text-white rounded-xl text-sm font-semibold hover:bg-indigo-700 disabled:opacity-40 transition-all flex items-center gap-2">
|
| 490 |
-
{trackLoading ? <Spinner /> : 'Track'}
|
| 491 |
-
</button>
|
| 492 |
-
</div>
|
| 493 |
-
|
| 494 |
-
{trackResult && (
|
| 495 |
-
<div className="animate-slide-up">
|
| 496 |
-
{trackResult.error ? (
|
| 497 |
-
<div className="p-4 bg-red-50 border border-red-200 rounded-xl text-sm text-red-600">
|
| 498 |
-
{trackResult.error}
|
| 499 |
-
</div>
|
| 500 |
-
) : (
|
| 501 |
-
<div className="space-y-4">
|
| 502 |
-
{/* Status banner */}
|
| 503 |
-
<div className={`p-4 rounded-xl border flex items-center justify-between ${
|
| 504 |
-
trackResult.status === 'resolved'
|
| 505 |
-
? 'bg-emerald-50 border-emerald-200'
|
| 506 |
-
: 'bg-amber-50 border-amber-200'
|
| 507 |
-
}`}>
|
| 508 |
-
<div className="flex items-center gap-3">
|
| 509 |
-
<span className={`w-3 h-3 rounded-full ${trackResult.status === 'resolved' ? 'bg-emerald-500' : 'bg-amber-400 pulse-dot'}`}></span>
|
| 510 |
-
<span className={`font-semibold text-sm ${trackResult.status === 'resolved' ? 'text-emerald-700' : 'text-amber-700'}`}>
|
| 511 |
-
{trackResult.status === 'resolved' ? 'Complaint Resolved' : 'Under Review — Pending'}
|
| 512 |
-
</span>
|
| 513 |
-
</div>
|
| 514 |
-
<span className="text-xs text-gray-400">{new Date(trackResult.created_at).toLocaleDateString('en-IN')}</span>
|
| 515 |
-
</div>
|
| 516 |
-
|
| 517 |
-
<p className="text-sm text-gray-700 leading-relaxed">{trackResult.summary}</p>
|
| 518 |
-
|
| 519 |
-
<div className="grid grid-cols-2 gap-3">
|
| 520 |
-
{[
|
| 521 |
-
{ label: 'Department', value: `${DEPT_ICONS[trackResult.department]||'📋'} ${trackResult.department}` },
|
| 522 |
-
{ label: 'Urgency', value: trackResult.urgency },
|
| 523 |
-
{ label: 'ETA', value: trackResult.estimated_resolution },
|
| 524 |
-
{ label: 'Status', value: trackResult.status === 'resolved' ? 'Resolved ✓' : 'Pending...' }
|
| 525 |
-
].map(item => (
|
| 526 |
-
<div key={item.label} className="bg-gray-50 rounded-xl p-3">
|
| 527 |
-
<p className="text-xs text-gray-400 mb-1">{item.label}</p>
|
| 528 |
-
<p className="text-sm font-medium text-gray-800">{item.value}</p>
|
| 529 |
-
</div>
|
| 530 |
-
))}
|
| 531 |
-
</div>
|
| 532 |
-
</div>
|
| 533 |
-
)}
|
| 534 |
-
</div>
|
| 535 |
-
)}
|
| 536 |
-
</div>
|
| 537 |
-
</div>
|
| 538 |
-
</div>
|
| 539 |
-
)}
|
| 540 |
-
|
| 541 |
-
{/* ── HOW IT WORKS ───────────────────────────────────────────────────── */}
|
| 542 |
-
<div className="mt-10 grid grid-cols-1 sm:grid-cols-3 gap-4">
|
| 543 |
-
{[
|
| 544 |
-
{ step: '01', icon: '✍️', title: 'Submit your complaint', desc: 'Type or speak in any Indian language. Our AI understands all of them.' },
|
| 545 |
-
{ step: '02', icon: '🤖', title: 'AI processes it', desc: 'Smart parser extracts key details, assigns department and urgency in under 3 seconds.' },
|
| 546 |
-
{ step: '03', icon: '📨', title: 'Authority is notified', desc: 'A structured report is routed to the right department. Critical complaints trigger instant alerts.' }
|
| 547 |
-
].map(item => (
|
| 548 |
-
<div key={item.step} className="bg-white/60 border border-gray-200/80 rounded-2xl p-5 backdrop-blur-sm">
|
| 549 |
-
<div className="flex items-start gap-3">
|
| 550 |
-
<span className="text-xl" style={{fontSize:'20px'}}>{item.icon}</span>
|
| 551 |
-
<div>
|
| 552 |
-
<p className="text-xs text-indigo-400 font-bold mb-1">Step {item.step}</p>
|
| 553 |
-
<p className="text-sm font-semibold text-gray-800 mb-1">{item.title}</p>
|
| 554 |
-
<p className="text-xs text-gray-500 leading-relaxed">{item.desc}</p>
|
| 555 |
-
</div>
|
| 556 |
-
</div>
|
| 557 |
-
</div>
|
| 558 |
-
))}
|
| 559 |
-
</div>
|
| 560 |
-
|
| 561 |
-
{/* Footer */}
|
| 562 |
-
<p className="text-center text-xs text-gray-400 mt-8 pb-4">
|
| 563 |
-
CitizenCare — Built for the National Hackathon · Powered by Smart AI parser, Supabase & Next.js
|
| 564 |
-
</p>
|
| 565 |
-
</div>
|
| 566 |
-
</div>
|
| 567 |
-
)
|
| 568 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Downloads/hackathon/civicai/pages/login.jsx
DELETED
|
@@ -1,108 +0,0 @@
|
|
| 1 |
-
import { useState } from 'react'
|
| 2 |
-
import { supabase } from '../lib/supabase'
|
| 3 |
-
import Link from 'next/link'
|
| 4 |
-
import { useRouter } from 'next/router'
|
| 5 |
-
|
| 6 |
-
export default function Login() {
|
| 7 |
-
const [email, setEmail] = useState('')
|
| 8 |
-
const [password, setPassword] = useState('')
|
| 9 |
-
const [loading, setLoading] = useState(false)
|
| 10 |
-
const [error, setError] = useState('')
|
| 11 |
-
const [isSignUp, setIsSignUp] = useState(false)
|
| 12 |
-
const router = useRouter()
|
| 13 |
-
|
| 14 |
-
const handleAuth = async (e) => {
|
| 15 |
-
e.preventDefault()
|
| 16 |
-
setLoading(true)
|
| 17 |
-
setError('')
|
| 18 |
-
|
| 19 |
-
try {
|
| 20 |
-
if (isSignUp) {
|
| 21 |
-
const { error } = await supabase.auth.signUp({ email, password })
|
| 22 |
-
if (error) throw error
|
| 23 |
-
setError('Check your email for confirmation link')
|
| 24 |
-
} else {
|
| 25 |
-
const { error } = await supabase.auth.signInWithPassword({ email, password })
|
| 26 |
-
if (error) throw error
|
| 27 |
-
router.push('/dashboard')
|
| 28 |
-
}
|
| 29 |
-
} catch (err) {
|
| 30 |
-
setError(err.message)
|
| 31 |
-
} finally {
|
| 32 |
-
setLoading(false)
|
| 33 |
-
}
|
| 34 |
-
}
|
| 35 |
-
|
| 36 |
-
return (
|
| 37 |
-
<div className="min-h-screen bg-gradient-to-br from-blue-50 via-indigo-50 to-purple-50 flex items-center justify-center p-4">
|
| 38 |
-
<div className="max-w-md w-full bg-white rounded-2xl shadow-xl p-8">
|
| 39 |
-
<div className="text-center mb-8">
|
| 40 |
-
<div className="w-16 h-16 bg-indigo-600 rounded-2xl flex items-center justify-center mx-auto mb-4">
|
| 41 |
-
<span className="text-white text-2xl font-bold">C</span>
|
| 42 |
-
</div>
|
| 43 |
-
<h1 className="text-2xl font-bold text-gray-900 mb-2">
|
| 44 |
-
{isSignUp ? 'Create Account' : 'Welcome Back'}
|
| 45 |
-
</h1>
|
| 46 |
-
<p className="text-gray-600">
|
| 47 |
-
{isSignUp ? 'Sign up to access the authority dashboard' : 'Sign in to your authority account'}
|
| 48 |
-
</p>
|
| 49 |
-
</div>
|
| 50 |
-
|
| 51 |
-
<form onSubmit={handleAuth} className="space-y-6">
|
| 52 |
-
<div>
|
| 53 |
-
<label className="block text-sm font-medium text-gray-700 mb-2">Email</label>
|
| 54 |
-
<input
|
| 55 |
-
type="email"
|
| 56 |
-
value={email}
|
| 57 |
-
onChange={(e) => setEmail(e.target.value)}
|
| 58 |
-
className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-all"
|
| 59 |
-
placeholder="authority@city.gov.in"
|
| 60 |
-
required
|
| 61 |
-
/>
|
| 62 |
-
</div>
|
| 63 |
-
|
| 64 |
-
<div>
|
| 65 |
-
<label className="block text-sm font-medium text-gray-700 mb-2">Password</label>
|
| 66 |
-
<input
|
| 67 |
-
type="password"
|
| 68 |
-
value={password}
|
| 69 |
-
onChange={(e) => setPassword(e.target.value)}
|
| 70 |
-
className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-all"
|
| 71 |
-
placeholder="Enter your password"
|
| 72 |
-
required
|
| 73 |
-
/>
|
| 74 |
-
</div>
|
| 75 |
-
|
| 76 |
-
{error && (
|
| 77 |
-
<div className="p-3 bg-red-50 border border-red-200 rounded-xl text-sm text-red-600">
|
| 78 |
-
{error}
|
| 79 |
-
</div>
|
| 80 |
-
)}
|
| 81 |
-
|
| 82 |
-
<button
|
| 83 |
-
type="submit"
|
| 84 |
-
disabled={loading}
|
| 85 |
-
className="w-full bg-indigo-600 text-white py-3 rounded-xl font-semibold hover:bg-indigo-700 disabled:opacity-50 transition-all"
|
| 86 |
-
>
|
| 87 |
-
{loading ? 'Please wait...' : (isSignUp ? 'Create Account' : 'Sign In')}
|
| 88 |
-
</button>
|
| 89 |
-
</form>
|
| 90 |
-
|
| 91 |
-
<div className="mt-6 text-center">
|
| 92 |
-
<button
|
| 93 |
-
onClick={() => setIsSignUp(!isSignUp)}
|
| 94 |
-
className="text-indigo-600 hover:text-indigo-700 text-sm"
|
| 95 |
-
>
|
| 96 |
-
{isSignUp ? 'Already have an account? Sign in' : 'Need an account? Sign up'}
|
| 97 |
-
</button>
|
| 98 |
-
</div>
|
| 99 |
-
|
| 100 |
-
<div className="mt-4 text-center">
|
| 101 |
-
<Link href="/" className="text-gray-500 hover:text-gray-700 text-sm">
|
| 102 |
-
← Back to citizen portal
|
| 103 |
-
</Link>
|
| 104 |
-
</div>
|
| 105 |
-
</div>
|
| 106 |
-
</div>
|
| 107 |
-
)
|
| 108 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Downloads/hackathon/civicai/pages/support.jsx
DELETED
|
@@ -1,101 +0,0 @@
|
|
| 1 |
-
import Link from 'next/link'
|
| 2 |
-
|
| 3 |
-
const FAQ_ITEMS = [
|
| 4 |
-
{
|
| 5 |
-
question: 'How does the AI process my complaint?',
|
| 6 |
-
answer: 'Our AI analyzes your complaint text using keyword detection and natural language processing to automatically categorize it, determine urgency, and route it to the appropriate government department.'
|
| 7 |
-
},
|
| 8 |
-
{
|
| 9 |
-
question: 'What languages are supported?',
|
| 10 |
-
answer: 'We support 10 Indian languages: English, Hindi, Telugu, Tamil, Kannada, Marathi, Bengali, Gujarati, Punjabi, and Odia. The AI detects the language automatically.'
|
| 11 |
-
},
|
| 12 |
-
{
|
| 13 |
-
question: 'How long does it take to resolve a complaint?',
|
| 14 |
-
answer: 'Resolution time depends on urgency: Critical issues (12 hours), High priority (24-48 hours), Medium (3-5 days), Low priority (7-14 days).'
|
| 15 |
-
},
|
| 16 |
-
{
|
| 17 |
-
question: 'Can I track my complaint status?',
|
| 18 |
-
answer: 'Yes! Use the tracking feature on the main page with your complaint ID. You can also check the status in real-time.'
|
| 19 |
-
},
|
| 20 |
-
{
|
| 21 |
-
question: 'What if my complaint is urgent?',
|
| 22 |
-
answer: 'Critical complaints trigger instant alerts to authorities. Use keywords like "accident", "emergency", or "collapsed" to mark it as critical.'
|
| 23 |
-
},
|
| 24 |
-
{
|
| 25 |
-
question: 'How do I know which department handles my issue?',
|
| 26 |
-
answer: 'The AI automatically detects the relevant department based on keywords in your complaint. You can see this in the complaint summary.'
|
| 27 |
-
},
|
| 28 |
-
{
|
| 29 |
-
question: 'Can I submit complaints anonymously?',
|
| 30 |
-
answer: 'Yes, complaints are submitted anonymously. Only the complaint content and location (if provided) are stored.'
|
| 31 |
-
},
|
| 32 |
-
{
|
| 33 |
-
question: 'What happens after I submit a complaint?',
|
| 34 |
-
answer: 'Your complaint is processed instantly, categorized, and routed to the relevant department. Authorities receive structured reports with action items.'
|
| 35 |
-
}
|
| 36 |
-
]
|
| 37 |
-
|
| 38 |
-
export default function Support() {
|
| 39 |
-
return (
|
| 40 |
-
<div className="min-h-screen" style={{ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%)' }}>
|
| 41 |
-
{/* ── NAVBAR ─────────────────────────────────────────────────────────── */}
|
| 42 |
-
<nav className="bg-white/80 backdrop-blur border-b border-gray-200/60 sticky top-0 z-30">
|
| 43 |
-
<div className="max-w-4xl mx-auto px-4 h-14 flex items-center justify-between">
|
| 44 |
-
<div className="flex items-center gap-2.5">
|
| 45 |
-
<div className="w-8 h-8 bg-indigo-600 rounded-lg flex items-center justify-center">
|
| 46 |
-
<span className="text-white text-sm font-bold">C</span>
|
| 47 |
-
</div>
|
| 48 |
-
<div>
|
| 49 |
-
<span className="font-semibold text-gray-900 text-sm">CitizenCare</span>
|
| 50 |
-
<span className="text-gray-400 text-xs ml-2 hidden sm:inline">Support Center</span>
|
| 51 |
-
</div>
|
| 52 |
-
</div>
|
| 53 |
-
<div className="flex items-center gap-3">
|
| 54 |
-
<Link href="/dashboard"
|
| 55 |
-
className="text-xs font-medium text-indigo-600 border border-indigo-200 px-3 py-1.5 rounded-lg hover:bg-indigo-50 transition-all">
|
| 56 |
-
Authority Dashboard →
|
| 57 |
-
</Link>
|
| 58 |
-
</div>
|
| 59 |
-
</div>
|
| 60 |
-
</nav>
|
| 61 |
-
|
| 62 |
-
<div className="max-w-4xl mx-auto px-4 py-8">
|
| 63 |
-
<div className="text-center mb-8">
|
| 64 |
-
<h1 className="text-3xl sm:text-4xl font-bold text-white mb-3 leading-tight">
|
| 65 |
-
Help & Support
|
| 66 |
-
</h1>
|
| 67 |
-
<p className="text-white/80 text-base max-w-xl mx-auto leading-relaxed">
|
| 68 |
-
Find answers to common questions about using CitizenCare
|
| 69 |
-
</p>
|
| 70 |
-
</div>
|
| 71 |
-
|
| 72 |
-
<div className="space-y-4">
|
| 73 |
-
{FAQ_ITEMS.map((item, index) => (
|
| 74 |
-
<details key={index} className="bg-white/90 backdrop-blur rounded-2xl border border-white/20 shadow-sm overflow-hidden">
|
| 75 |
-
<summary className="px-6 py-5 font-semibold text-gray-900 cursor-pointer hover:bg-white/50 transition-all">
|
| 76 |
-
{item.question}
|
| 77 |
-
</summary>
|
| 78 |
-
<div className="px-6 pb-5 text-gray-700 leading-relaxed">
|
| 79 |
-
{item.answer}
|
| 80 |
-
</div>
|
| 81 |
-
</details>
|
| 82 |
-
))}
|
| 83 |
-
</div>
|
| 84 |
-
|
| 85 |
-
<div className="mt-8 text-center">
|
| 86 |
-
<p className="text-white/80 mb-4">Still need help?</p>
|
| 87 |
-
<Link href="/" className="inline-flex items-center gap-2 bg-white/20 backdrop-blur border border-white/30 text-white px-6 py-3 rounded-xl hover:bg-white/30 transition-all">
|
| 88 |
-
<span>📞</span>
|
| 89 |
-
Contact Support
|
| 90 |
-
</Link>
|
| 91 |
-
</div>
|
| 92 |
-
|
| 93 |
-
<div className="mt-8 text-center">
|
| 94 |
-
<Link href="/" className="text-white/60 hover:text-white text-sm">
|
| 95 |
-
← Back to Home
|
| 96 |
-
</Link>
|
| 97 |
-
</div>
|
| 98 |
-
</div>
|
| 99 |
-
</div>
|
| 100 |
-
)
|
| 101 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Downloads/hackathon/civicai/postcss.config.js
DELETED
|
@@ -1 +0,0 @@
|
|
| 1 |
-
module.exports = { plugins: { tailwindcss: {}, autoprefixer: {} } }
|
|
|
|
|
|
Downloads/hackathon/civicai/styles/globals.css
DELETED
|
@@ -1,34 +0,0 @@
|
|
| 1 |
-
@tailwind base;
|
| 2 |
-
@tailwind components;
|
| 3 |
-
@tailwind utilities;
|
| 4 |
-
|
| 5 |
-
* { box-sizing: border-box; }
|
| 6 |
-
|
| 7 |
-
body {
|
| 8 |
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Inter', sans-serif;
|
| 9 |
-
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
| 10 |
-
}
|
| 11 |
-
|
| 12 |
-
@keyframes spin-slow {
|
| 13 |
-
from { transform: rotate(0deg); }
|
| 14 |
-
to { transform: rotate(360deg); }
|
| 15 |
-
}
|
| 16 |
-
|
| 17 |
-
@keyframes pulse-dot {
|
| 18 |
-
0%, 100% { opacity: 1; transform: scale(1); }
|
| 19 |
-
50% { opacity: 0.5; transform: scale(0.8); }
|
| 20 |
-
}
|
| 21 |
-
|
| 22 |
-
@keyframes slide-up {
|
| 23 |
-
from { opacity: 0; transform: translateY(16px); }
|
| 24 |
-
to { opacity: 1; transform: translateY(0); }
|
| 25 |
-
}
|
| 26 |
-
|
| 27 |
-
@keyframes fade-in {
|
| 28 |
-
from { opacity: 0; }
|
| 29 |
-
to { opacity: 1; }
|
| 30 |
-
}
|
| 31 |
-
|
| 32 |
-
.animate-slide-up { animation: slide-up 0.35s ease forwards; }
|
| 33 |
-
.animate-fade-in { animation: fade-in 0.25s ease forwards; }
|
| 34 |
-
.pulse-dot { animation: pulse-dot 1.2s ease-in-out infinite; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Downloads/hackathon/civicai/tailwind.config.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
| 1 |
-
/** @type {import('tailwindcss').Config} */
|
| 2 |
-
module.exports = {
|
| 3 |
-
content: ['./pages/**/*.{js,jsx}', './components/**/*.{js,jsx}'],
|
| 4 |
-
theme: {
|
| 5 |
-
extend: {
|
| 6 |
-
colors: {
|
| 7 |
-
primary: {
|
| 8 |
-
50: '#eff6ff',
|
| 9 |
-
100: '#dbeafe',
|
| 10 |
-
200: '#bfdbfe',
|
| 11 |
-
300: '#93c5fd',
|
| 12 |
-
400: '#60a5fa',
|
| 13 |
-
500: '#3b82f6',
|
| 14 |
-
600: '#2563eb',
|
| 15 |
-
700: '#1d4ed8',
|
| 16 |
-
800: '#1e40af',
|
| 17 |
-
900: '#1e3a8a',
|
| 18 |
-
},
|
| 19 |
-
secondary: {
|
| 20 |
-
50: '#f8fafc',
|
| 21 |
-
100: '#f1f5f9',
|
| 22 |
-
200: '#e2e8f0',
|
| 23 |
-
300: '#cbd5e1',
|
| 24 |
-
400: '#94a3b8',
|
| 25 |
-
500: '#64748b',
|
| 26 |
-
600: '#475569',
|
| 27 |
-
700: '#334155',
|
| 28 |
-
800: '#1e293b',
|
| 29 |
-
900: '#0f172a',
|
| 30 |
-
}
|
| 31 |
-
}
|
| 32 |
-
}
|
| 33 |
-
},
|
| 34 |
-
plugins: []
|
| 35 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|