commit
32a36cceff
444 files changed
+67186
No files matched your search
@@ -0,0 +1,665 @@
|
||||
# Dashboard Solusi AI Peternakan Ayam
|
||||
|
||||
Dashboard monitoring dan manajemen peternakan ayam berbasis web dengan integrasi IoT, AI, dan database PostgreSQL untuk penyimpanan data siklus produksi.
|
||||
|
||||
## 📋 Daftar Isi
|
||||
|
||||
- [Fitur Utama](#fitur-utama)
|
||||
- [Teknologi](#teknologi)
|
||||
- [Deployment](#deployment)
|
||||
- [Persyaratan Sistem](#persyaratan-sistem)
|
||||
- [Instalasi](#instalasi)
|
||||
- [Cara Menjalankan](#cara-menjalankan)
|
||||
- [Struktur Proyek](#struktur-proyek)
|
||||
- [API Documentation](#api-documentation)
|
||||
- [Database Schema](#database-schema)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
|
||||
## 🚀 Fitur Utama
|
||||
|
||||
### Frontend
|
||||
|
||||
- **Dashboard Utama**: Monitoring real-time KPI, alert, dan kondisi kandang
|
||||
- **Linimasa Siklus**: Manajemen siklus produksi dengan timeline visual
|
||||
- **Hitung Ayam**:
|
||||
- Dashboard perhitungan populasi
|
||||
- **Manajemen Data**: CRUD data mortalitas dengan penyimpanan database
|
||||
- **Monitoring Berat**: Tracking berat ayam dengan distribusi dan statistik
|
||||
- **Standar Performa**: Perbandingan dengan standar Cobb
|
||||
- **Penjadwalan Pakan**: Rekomendasi jadwal pemberian pakan
|
||||
- **Feed Wastage**: Monitoring pemborosan pakan
|
||||
- **Behavior Analysis**: Analisis perilaku ayam dengan AI
|
||||
- **Network Monitoring**: Status koneksi IoT devices
|
||||
- **ERP Integration**: Sinkronisasi dengan sistem ERP
|
||||
|
||||
### Backend (PostgreSQL Database)
|
||||
|
||||
- **Database**: PostgreSQL untuk penyimpanan data siklus dan mortalitas
|
||||
- **RESTful API**: Endpoint untuk CRUD operations
|
||||
- **Auto-seeding**: Database otomatis terisi data awal saat pertama kali dijalankan
|
||||
- **Persistent Storage**: Semua perubahan data tersimpan permanen
|
||||
|
||||
## 🛠 Teknologi
|
||||
|
||||
### Frontend
|
||||
|
||||
- **React 18** dengan TypeScript
|
||||
- **Vite** - Build tool & dev server
|
||||
- **Recharts** - Data visualization
|
||||
- **Tailwind CSS** - Styling
|
||||
- **Context API** - State management
|
||||
|
||||
### Backend
|
||||
|
||||
- **Node.js** dengan Express
|
||||
- **PostgreSQL** (pg) - Database
|
||||
- **CORS** - Cross-origin support
|
||||
|
||||
### Deployment
|
||||
|
||||
- **Docker** - Containerization
|
||||
- **Docker Compose** - Multi-container orchestration (3 containers: frontend, backend, database)
|
||||
- **Nginx** - Reverse proxy & static file serving
|
||||
- **PostgreSQL** - Database container
|
||||
|
||||
## 🐳 Deployment
|
||||
|
||||
### Docker Deployment (Recommended for Production)
|
||||
|
||||
Deploy dengan 3 container (frontend + backend + PostgreSQL database) menggunakan Docker Compose:
|
||||
|
||||
```bash
|
||||
# Quick start
|
||||
docker-compose up -d --build
|
||||
|
||||
# Access application
|
||||
http://your-server-ip
|
||||
```
|
||||
|
||||
**Keuntungan Docker:**
|
||||
|
||||
- ✅ Easy deployment dan scaling
|
||||
- ✅ Isolated environment
|
||||
- ✅ Consistent across different servers
|
||||
- ✅ Automatic restarts
|
||||
- ✅ Built-in health checks
|
||||
|
||||
**📚 Complete Docker Guide:** [DOCKER.md](DOCKER.md)
|
||||
|
||||
**Local Postgres / sync from server / DBeaver:** [docs/LOCAL_DATABASE_GUIDE.md](docs/LOCAL_DATABASE_GUIDE.md)
|
||||
|
||||
### Manual Deployment
|
||||
|
||||
Untuk development atau testing lokal, lihat [Instalasi](#instalasi) dan [Cara Menjalankan](#cara-menjalankan) di bawah.
|
||||
|
||||
## 📦 Persyaratan Sistem
|
||||
|
||||
### Untuk Docker Deployment
|
||||
|
||||
- **Docker**: v20.10+
|
||||
- **Docker Compose**: v2.0+
|
||||
- **RAM**: Minimum 2GB
|
||||
- **Disk**: 10GB free space
|
||||
- **Port**: 80 (frontend)
|
||||
|
||||
### Untuk Manual Installation
|
||||
|
||||
- **Node.js**: v18.0.0 atau lebih tinggi
|
||||
- **npm**: v9.0.0 atau lebih tinggi
|
||||
- **Port yang tersedia**:
|
||||
- Frontend: 3001 (atau port lain jika 3001 terpakai)
|
||||
- Backend: 5001
|
||||
|
||||
## 💿 Instalasi
|
||||
|
||||
### 1. Clone Repository
|
||||
|
||||
```bash
|
||||
git clone <repository-url>
|
||||
cd dashboard-solusi-ai-peternakan-ayam
|
||||
```
|
||||
|
||||
### 2. Install Dependencies Frontend
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
### 3. Install Dependencies Backend
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
npm install
|
||||
cd ..
|
||||
```
|
||||
|
||||
## ▶️ Cara Menjalankan
|
||||
|
||||
### Opsi 1: Menjalankan Secara Manual (Recommended untuk Development)
|
||||
|
||||
#### Terminal 1 - Backend Server
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Backend akan berjalan di: **http://localhost:5001**
|
||||
|
||||
Output yang diharapkan:
|
||||
|
||||
```
|
||||
========================================
|
||||
🚀 Server running on http://localhost:5001
|
||||
========================================
|
||||
|
||||
API Endpoints:
|
||||
GET /health
|
||||
GET /api/cycles
|
||||
GET /api/cycles/active
|
||||
...
|
||||
```
|
||||
|
||||
#### Terminal 2 - Frontend Server
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Frontend akan berjalan di: **http://localhost:3001** (atau port lain jika terpakai)
|
||||
|
||||
Output yang diharapkan:
|
||||
|
||||
```
|
||||
VITE v6.4.1 ready in 155 ms
|
||||
|
||||
➜ Local: http://localhost:3001/
|
||||
```
|
||||
|
||||
### Opsi 2: Menjalankan dengan satu perintah
|
||||
|
||||
Buka dua terminal secara terpisah:
|
||||
|
||||
**Terminal 1:**
|
||||
|
||||
```bash
|
||||
cd backend && npm run dev
|
||||
```
|
||||
|
||||
**Terminal 2:**
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Atau gunakan terminal multiplexer seperti `tmux` atau `screen`.
|
||||
|
||||
## 📁 Struktur Proyek
|
||||
|
||||
```
|
||||
dashboard-solusi-ai-peternakan-ayam/
|
||||
├── backend/ # Backend Node.js + PostgreSQL
|
||||
│ ├── database/
|
||||
│ │ ├── db.js # PostgreSQL connection & pool setup
|
||||
│ │ ├── schema.sql # Database schema
|
||||
│ │ ├── seed-postgres.js # Data seeding script
|
||||
│ │ └── migrations/ # Database migrations
|
||||
│ ├── models/
|
||||
│ │ ├── Cycle.js # Cycle data model
|
||||
│ │ └── Mortality.js # Mortality data model
|
||||
│ ├── routes/
|
||||
│ │ ├── cycles.js # Cycle endpoints
|
||||
│ │ └── mortality.js # Mortality endpoints
|
||||
│ ├── server.js # Express server
|
||||
│ ├── package.json
|
||||
│ └── .env # Environment variables
|
||||
├── components/ # React components
|
||||
│ ├── counting/
|
||||
│ │ └── DataManagementPage.tsx # Mortality data management
|
||||
│ ├── CycleTimeline.tsx # Cycle timeline component
|
||||
│ └── ...
|
||||
├── context/ # React context & stores
|
||||
│ ├── AppContext.tsx
|
||||
│ └── stores/
|
||||
│ └── useStaticDataStore.ts # Store with DB integration
|
||||
├── services/
|
||||
│ └── apiService.ts # API client with DB methods
|
||||
├── scripts/ # Database & deployment scripts
|
||||
│ ├── backup-postgres.sh # Backup database
|
||||
│ ├── restore-postgres-local.sh # Restore from backup
|
||||
│ └── fetch-prod-db.sh # Fetch production data
|
||||
├── mockData/ # Mock data for demo mode
|
||||
├── types/ # TypeScript type definitions
|
||||
├── public/ # Static assets
|
||||
├── docker-compose.yml # 3-container orchestration
|
||||
├── package.json
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## 📡 API Documentation
|
||||
|
||||
Base URL: `http://localhost:5001/api`
|
||||
|
||||
### Health Check
|
||||
|
||||
```http
|
||||
GET /health
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"timestamp": "2025-12-22T03:02:20.793Z"
|
||||
}
|
||||
```
|
||||
|
||||
### Cycles Endpoints
|
||||
|
||||
#### Get All Cycles
|
||||
|
||||
```http
|
||||
GET /api/cycles
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": [
|
||||
{
|
||||
"id": "CYCLE-JBW-2025-12-10",
|
||||
"totalDays": 42,
|
||||
"currentDay": 7,
|
||||
"startDate": "2025-12-10",
|
||||
"endDate": "2026-01-20",
|
||||
"chickInWeight": null,
|
||||
"docInCount": 20000,
|
||||
"status": "Active",
|
||||
"createdAt": "2025-12-22 02:59:17",
|
||||
"updatedAt": "2025-12-22 02:59:17"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### Get Active Cycle
|
||||
|
||||
```http
|
||||
GET /api/cycles/active
|
||||
```
|
||||
|
||||
#### Get Cycle by ID
|
||||
|
||||
```http
|
||||
GET /api/cycles/:id
|
||||
```
|
||||
|
||||
#### Update Cycle
|
||||
|
||||
```http
|
||||
PUT /api/cycles/:id
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"totalDays": 42,
|
||||
"currentDay": 7,
|
||||
"startDate": "2025-12-10",
|
||||
"endDate": "2026-01-20",
|
||||
"chickInWeight": 42,
|
||||
"docInCount": 20000,
|
||||
"status": "Active"
|
||||
}
|
||||
```
|
||||
|
||||
#### Delete Cycle
|
||||
|
||||
```http
|
||||
DELETE /api/cycles/:id
|
||||
```
|
||||
|
||||
### Mortality Endpoints
|
||||
|
||||
#### Get All Mortality Records for Cycle
|
||||
|
||||
```http
|
||||
GET /api/mortality/:cycleId
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": [
|
||||
{
|
||||
"id": 1,
|
||||
"cycleId": "CYCLE-JBW-2025-12-10",
|
||||
"day": 0,
|
||||
"mortalityCount": 25,
|
||||
"isEdited": true,
|
||||
"createdAt": "2025-12-22 03:00:00",
|
||||
"updatedAt": "2025-12-22 03:00:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### Get Mortality Record for Specific Day
|
||||
|
||||
```http
|
||||
GET /api/mortality/:cycleId/:day
|
||||
```
|
||||
|
||||
#### Update/Create Mortality Record
|
||||
|
||||
```http
|
||||
PUT /api/mortality/:cycleId/:day
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"mortalityCount": 30
|
||||
}
|
||||
```
|
||||
|
||||
#### Delete Mortality Record (Reset to Default)
|
||||
|
||||
```http
|
||||
DELETE /api/mortality/:cycleId/:day
|
||||
```
|
||||
|
||||
## 🗄️ Database Schema
|
||||
|
||||
### Table: cycles
|
||||
|
||||
Menyimpan informasi siklus produksi.
|
||||
|
||||
| Column | Type | Description |
|
||||
| --------------- | ------- | ----------------------------------------- |
|
||||
| id | TEXT | Primary key, format: CYCLE-JBW-YYYY-MM-DD |
|
||||
| total_days | INTEGER | Total hari dalam siklus (biasanya 42) |
|
||||
| current_day | INTEGER | Hari saat ini dalam siklus |
|
||||
| start_date | TEXT | Tanggal mulai (ISO format: YYYY-MM-DD) |
|
||||
| end_date | TEXT | Tanggal akhir (ISO format: YYYY-MM-DD) |
|
||||
| chick_in_weight | INTEGER | Berat DOC in (gram) |
|
||||
| doc_in_count | INTEGER | Jumlah DOC in (ekor) |
|
||||
| status | TEXT | Status: 'Active', 'Completed', 'Upcoming' |
|
||||
| created_at | TEXT | Timestamp pembuatan |
|
||||
| updated_at | TEXT | Timestamp update terakhir |
|
||||
|
||||
### Table: mortality_records
|
||||
|
||||
Menyimpan data mortalitas harian.
|
||||
|
||||
| Column | Type | Description |
|
||||
| --------------- | ------- | ------------------------------------ |
|
||||
| id | INTEGER | Primary key (auto increment) |
|
||||
| cycle_id | TEXT | Foreign key ke cycles.id |
|
||||
| day | INTEGER | Hari ke berapa dalam siklus |
|
||||
| mortality_count | INTEGER | Jumlah mortalitas hari ini |
|
||||
| is_edited | BOOLEAN | Flag apakah data sudah diedit manual |
|
||||
| created_at | TEXT | Timestamp pembuatan |
|
||||
| updated_at | TEXT | Timestamp update terakhir |
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- UNIQUE(cycle_id, day) - Satu cycle hanya bisa punya satu record per hari
|
||||
- FOREIGN KEY cascade delete - Jika cycle dihapus, mortality records ikut terhapus
|
||||
|
||||
### Indexes
|
||||
|
||||
- `idx_mortality_cycle_id` - Index pada cycle_id untuk query cepat
|
||||
- `idx_mortality_day` - Index pada day
|
||||
- `idx_cycles_status` - Index pada status untuk filter cycle aktif
|
||||
- `idx_cycles_start_date` - Index pada start_date untuk sorting
|
||||
|
||||
## 🔧 Troubleshooting
|
||||
|
||||
### Port 5001 sudah terpakai
|
||||
|
||||
Jika port 5001 sudah digunakan oleh aplikasi lain (contoh: AirPlay on macOS):
|
||||
|
||||
1. Edit file `backend/.env`:
|
||||
|
||||
```env
|
||||
PORT=5002 # Ganti ke port lain yang tersedia
|
||||
```
|
||||
|
||||
2. Update URL di `services/apiService.ts`:
|
||||
|
||||
```typescript
|
||||
const DB_API_BASE_URL = 'http://localhost:5002/api';
|
||||
```
|
||||
|
||||
3. Restart backend server
|
||||
|
||||
### Port 3001 sudah terpakai
|
||||
|
||||
Vite akan otomatis mencari port lain yang tersedia. Perhatikan output di terminal untuk melihat port yang digunakan.
|
||||
|
||||
### Database tidak terbuat
|
||||
|
||||
Jika database tidak terbuat otomatis:
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
node database/seed-postgres.js
|
||||
```
|
||||
|
||||
### CORS Error
|
||||
|
||||
Jika frontend tidak bisa mengakses backend, pastikan:
|
||||
|
||||
1. Backend server sudah berjalan
|
||||
2. Port di `backend/server.js` sesuai dengan konfigurasi CORS:
|
||||
|
||||
```javascript
|
||||
origin: ['http://localhost:3001', 'http://localhost:5173'];
|
||||
```
|
||||
|
||||
### Frontend tidak load data dari database
|
||||
|
||||
1. Buka browser console (F12)
|
||||
2. Cek apakah ada error dari API calls
|
||||
3. Pastikan backend server berjalan: `curl http://localhost:5001/health`
|
||||
4. Cek network tab untuk melihat request/response
|
||||
|
||||
### Error "Failed to load cycles from database"
|
||||
|
||||
1. Pastikan backend server sudah berjalan
|
||||
2. Test backend endpoint: `curl http://localhost:5001/api/cycles`
|
||||
3. Cek backend logs untuk melihat error detail
|
||||
|
||||
### Reset Database ke Data Awal
|
||||
|
||||
**For Local PostgreSQL Development:**
|
||||
|
||||
```bash
|
||||
# Stop backend if running, then:
|
||||
./scripts/restore-postgres-local.sh --reset
|
||||
|
||||
# Or manually run seed:
|
||||
cd backend
|
||||
node database/seed-postgres.js
|
||||
```
|
||||
|
||||
**For Docker:**
|
||||
|
||||
```bash
|
||||
# Reset database by removing volume and restarting:
|
||||
docker-compose down -v
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## 📝 Fitur Database
|
||||
|
||||
### Auto-Seeding
|
||||
|
||||
Database akan otomatis terisi dengan 4 siklus produksi saat pertama kali server backend dijalankan:
|
||||
|
||||
1. **CYCLE-JBW-2025-05-20** - Completed (20 Mei - 30 Juni 2025)
|
||||
2. **CYCLE-JBW-2025-07-11** - Completed (11 Juli - 21 Agustus 2025)
|
||||
3. **CYCLE-JBW-2025-10-22** - Completed (22 Oktober - 2 Desember 2025)
|
||||
4. **CYCLE-JBW-2025-12-10** - Active (10 Desember 2025 - 20 Januari 2026) ✓
|
||||
|
||||
### Data Persistence
|
||||
|
||||
Semua perubahan data akan tersimpan permanen di PostgreSQL database:
|
||||
|
||||
- ✅ Perubahan tanggal siklus di Linimasa
|
||||
- ✅ Update DOC In dan Berat DOC di pengaturan siklus
|
||||
- ✅ Edit data mortalitas di halaman Manajemen Data
|
||||
- ✅ Reset data mortalitas ke nilai default
|
||||
|
||||
### Backup Database
|
||||
|
||||
**Production/Docker:**
|
||||
|
||||
```bash
|
||||
./scripts/backup-postgres.sh
|
||||
```
|
||||
|
||||
Backups are saved in `./backups/` as `dashboard_db-YYYYMMDD-HHMMSS.sql.gz`
|
||||
|
||||
**Fetch from production server:**
|
||||
|
||||
```bash
|
||||
REMOTE_USER=your-user \
|
||||
REMOTE_HOST=your-host \
|
||||
REMOTE_PROJECT_DIR=/path/to/project \
|
||||
./scripts/fetch-prod-db.sh
|
||||
```
|
||||
|
||||
## 🔐 Environment Variables
|
||||
|
||||
### Backend (.env)
|
||||
|
||||
File: `backend/.env`
|
||||
|
||||
```env
|
||||
PORT=5001
|
||||
NODE_ENV=development
|
||||
|
||||
# PostgreSQL Configuration
|
||||
DB_HOST=localhost
|
||||
DB_PORT=5432
|
||||
DB_USER=dashboard_user
|
||||
DB_PASSWORD=your_password
|
||||
DB_NAME=dashboard_db
|
||||
DB_SSL=false
|
||||
```
|
||||
|
||||
### Frontend (.env.local) - Optional
|
||||
|
||||
File: `.env.local` (create if needed)
|
||||
|
||||
```env
|
||||
VITE_API_URL=http://localhost:5001/api
|
||||
```
|
||||
|
||||
## 🎯 Testing
|
||||
|
||||
### Test Backend API
|
||||
|
||||
```bash
|
||||
# Health check
|
||||
curl http://localhost:5001/health
|
||||
|
||||
# Get all cycles
|
||||
curl http://localhost:5001/api/cycles
|
||||
|
||||
# Get active cycle
|
||||
curl http://localhost:5001/api/cycles/active
|
||||
|
||||
# Get mortality records
|
||||
curl http://localhost:5001/api/mortality/CYCLE-JBW-2025-12-10
|
||||
```
|
||||
|
||||
### Test Frontend
|
||||
|
||||
1. Buka http://localhost:3001 di browser
|
||||
2. Navigasi ke "Linimasa Siklus Produksi"
|
||||
3. Klik "Edit" pada siklus aktif
|
||||
4. Ubah tanggal atau DOC count
|
||||
5. Save dan refresh - data harus tetap tersimpan
|
||||
6. Navigasi ke "Hitung Ayam" > "Manajemen Data"
|
||||
7. Edit nilai mortalitas
|
||||
8. Save dan refresh - data harus tetap tersimpan
|
||||
|
||||
## 📚 Cara Menggunakan Aplikasi
|
||||
|
||||
### 1. Mengelola Siklus Produksi
|
||||
|
||||
**Linimasa Siklus:**
|
||||
|
||||
- Lihat semua siklus produksi (completed, active, upcoming)
|
||||
- Edit tanggal mulai dan akhir
|
||||
- Set DOC In count dan berat DOC
|
||||
- Data tersimpan otomatis ke database
|
||||
|
||||
### 2. Manajemen Data Mortalitas
|
||||
|
||||
**Hitung Ayam > Manajemen Data:**
|
||||
|
||||
- Lihat data mortalitas per hari
|
||||
- Edit nilai mortalitas dengan klik "Edit"
|
||||
- Reset ke nilai default dengan klik tombol reset
|
||||
- Lihat statistik: populasi awal, populasi saat ini, total mortalitas, tingkat mortalitas
|
||||
- Filter data: cari per hari atau tampilkan hanya data yang diedit
|
||||
- Data tersimpan permanen di database
|
||||
|
||||
### 3. Monitoring Standar Performa
|
||||
|
||||
**Standar Performa > Cobb Standard:**
|
||||
|
||||
- Kapasitas kandang otomatis sync dengan DOC In count dari linimasa
|
||||
- Lihat grafik perbandingan berat aktual vs standar Cobb
|
||||
- Analisis FCR (Feed Conversion Ratio)
|
||||
|
||||
## 🚦 Status Proyek
|
||||
|
||||
- ✅ Frontend Dashboard
|
||||
- ✅ Backend API dengan PostgreSQL
|
||||
- ✅ Database Schema & Models
|
||||
- ✅ CRUD Cycles
|
||||
- ✅ CRUD Mortality Records
|
||||
- ✅ Frontend-Backend Integration
|
||||
- ✅ Auto-seeding Data
|
||||
- ✅ Data Persistence
|
||||
- ✅ Docker Deployment (3-container architecture)
|
||||
- ✅ Database Backup & Restore Scripts
|
||||
- ⏳ User Authentication (coming soon)
|
||||
- ⏳ Real-time WebSocket (coming soon)
|
||||
- ⏳ Data Export (CSV/Excel) (coming soon)
|
||||
|
||||
## 🤝 Kontribusi
|
||||
|
||||
Untuk berkontribusi pada proyek ini:
|
||||
|
||||
1. Fork repository
|
||||
2. Buat branch feature (`git checkout -b feature/AmazingFeature`)
|
||||
3. Commit perubahan (`git commit -m 'Add some AmazingFeature'`)
|
||||
4. Push ke branch (`git push origin feature/AmazingFeature`)
|
||||
5. Buat Pull Request
|
||||
|
||||
## 📄 License
|
||||
|
||||
Proyek ini menggunakan lisensi MIT.
|
||||
|
||||
## 👥 Tim Pengembang
|
||||
|
||||
- Development Team - PT Cipta Pola Solusi Prima
|
||||
- Dashboard & AI Integration - 2025
|
||||
|
||||
## 📞 Kontak
|
||||
|
||||
Untuk pertanyaan atau dukungan, silakan hubungi:
|
||||
|
||||
- Email: support@cpsp.id
|
||||
- Website: https://dashboard.cpsp.id
|
||||
|
||||
---
|
||||
|
||||
**Dibuat dengan ❤️ untuk kemajuan peternakan ayam Indonesia**
|
||||
Reference in new issue
Block a user