Compare commits
23 Commits
amalia/14-
...
join
| Author | SHA1 | Date | |
|---|---|---|---|
| e62909b070 | |||
| 30611802f4 | |||
| 854921935a | |||
| 191e567e12 | |||
| 474ced6a38 | |||
| 2b746b77e6 | |||
| 352469ce32 | |||
| 44b400cfb8 | |||
| e6b4adc8c2 | |||
| f5e36f5ac7 | |||
| fa9b883c2e | |||
| 3b58492680 | |||
| f990e2c82e | |||
| bf9ef48a70 | |||
| 97ae638472 | |||
| 183d40580d | |||
| 60702256a3 | |||
| 9e11208a13 | |||
| 0077ebda05 | |||
| e5b95a828d | |||
| 1f6791e9bd | |||
| 968202e34b | |||
| 0ce94e0e2b |
255
PANDUAN PENGGUNAAN.md
Normal file
255
PANDUAN PENGGUNAAN.md
Normal file
@@ -0,0 +1,255 @@
|
||||
# Panduan Penggunaan Sistem Desa Mandiri
|
||||
|
||||
## Daftar Isi
|
||||
1. [Gambaran Umum](#gambaran-umum)
|
||||
2. [Peran Pengguna dan Hak Akses](#peran-pengguna-dan-hak-akses)
|
||||
3. [Fitur-Fitur Utama dan Aksesnya](#fitur-fitur-utama-dan-aksesnya)
|
||||
4. [Cara Menggunakan Aplikasi](#cara-menggunakan-aplikasi)
|
||||
5. [Tips dan Trik](#tips-dan-trik)
|
||||
|
||||
## Gambaran Umum
|
||||
|
||||
Sistem Desa Mandiri adalah aplikasi web yang dirancang untuk membantu pengelolaan administrasi dan informasi di tingkat desa. Aplikasi ini dibangun dengan teknologi Next.js dan menyediakan berbagai fitur untuk mendukung kegiatan desa, mulai dari pengumuman, diskusi, manajemen proyek, hingga administrasi kependudukan.
|
||||
|
||||
## Peran Pengguna dan Hak Akses
|
||||
|
||||
Aplikasi ini memiliki beberapa peran pengguna dengan hak akses berbeda:
|
||||
|
||||
### 1. Super Admin
|
||||
- **Hak Akses**: Memiliki akses penuh ke semua fitur aplikasi
|
||||
- **Fungsi**: Mengelola seluruh sistem, termasuk pembuatan akun admin, pengaturan desa, dan manajemen sistem secara keseluruhan
|
||||
- **Dapat Mengakses**: Semua fitur dalam aplikasi
|
||||
|
||||
### 2. Admin Desa
|
||||
- **Hak Akses**: Memiliki akses ke fitur-fitur yang berkaitan dengan desa tertentu
|
||||
- **Fungsi**: Mengelola data dan informasi dalam lingkup desa tertentu
|
||||
- **Dapat Mengakses**: Semua fitur terkait desa yang dikelola, termasuk pengumuman, proyek, divisi, dan pengguna
|
||||
|
||||
### 3. Ketua Divisi
|
||||
- **Hak Akses**: Memiliki akses administratif dalam divisi tertentu
|
||||
- **Fungsi**: Mengelola anggota, proyek, dan kegiatan dalam divisi
|
||||
- **Dapat Mengakses**: Fitur-fitur terkait divisi yang dipimpin, termasuk manajemen anggota, proyek, diskusi, dan dokumentasi
|
||||
|
||||
### 4. Anggota Divisi
|
||||
- **Hak Akses**: Dapat mengakses dan berpartisipasi dalam kegiatan divisi
|
||||
- **Fungsi**: Menjalankan tugas dan berkontribusi dalam kegiatan divisi
|
||||
- **Dapat Mengakses**: Kegiatan dan informasi dalam divisi yang diikuti
|
||||
|
||||
### 5. Warga/Perangkat Desa
|
||||
- **Hak Akses**: Akses dasar ke fitur-fitur umum
|
||||
- **Fungsi**: Melihat informasi, berpartisipasi dalam diskusi umum
|
||||
- **Dapat Mengakses**: Pengumuman, diskusi umum, kalender kegiatan umum
|
||||
|
||||
## Fitur-Fitur Utama dan Aksesnya
|
||||
|
||||
### 1. Manajemen Pengguna
|
||||
- **Deskripsi**: Fitur untuk mendaftarkan dan mengelola data anggota desa serta mengatur hak akses berdasarkan peran
|
||||
- **Dapat Diakses Oleh**: Super Admin, Admin Desa
|
||||
- **Fungsi**:
|
||||
- Registrasi pengguna baru
|
||||
- Pengelolaan data pengguna
|
||||
- Penetapan peran pengguna
|
||||
- Pengelolaan grup dan posisi dalam desa
|
||||
|
||||
### 2. Pengumuman
|
||||
- **Deskripsi**: Fitur untuk membuat dan menyebarkan pengumuman penting kepada warga
|
||||
- **Dapat Diakses Oleh**: Super Admin, Admin Desa, Ketua Divisi (untuk divisi masing-masing)
|
||||
- **Fungsi**:
|
||||
- Membuat pengumuman baru
|
||||
- Menargetkan pengumuman ke grup atau divisi tertentu
|
||||
- Melampirkan file dalam pengumuman
|
||||
- Mengedit atau menghapus pengumuman
|
||||
|
||||
### 3. Diskusi Umum
|
||||
- **Deskripsi**: Forum diskusi umum untuk seluruh warga desa
|
||||
- **Dapat Diakses Oleh**: Seluruh pengguna terdaftar
|
||||
- **Fungsi**:
|
||||
- Membuat topik diskusi baru
|
||||
- Memberikan komentar dalam diskusi
|
||||
- Melihat riwayat diskusi
|
||||
- Melampirkan file dalam diskusi
|
||||
|
||||
### 4. Diskusi Divisi
|
||||
- **Deskripsi**: Forum diskusi internal dalam divisi-divisi dalam desa
|
||||
- **Dapat Diakses Oleh**: Anggota divisi yang bersangkutan
|
||||
- **Fungsi**:
|
||||
- Membuat topik diskusi internal divisi
|
||||
- Memberikan komentar dalam diskusi divisi
|
||||
- Menambahkan anggota ke dalam diskusi
|
||||
- Melampirkan dokumen terkait diskusi
|
||||
|
||||
### 5. Manajemen Proyek
|
||||
- **Deskripsi**: Fitur untuk membuat dan mengelola proyek-proyek desa
|
||||
- **Dapat Diakses Oleh**: Super Admin, Admin Desa, Ketua Divisi
|
||||
- **Fungsi**:
|
||||
- Membuat proyek baru
|
||||
- Menetapkan anggota tim proyek
|
||||
- Melacak kemajuan proyek dan tugas-tugasnya
|
||||
- Melampirkan dokumen dan tautan terkait proyek
|
||||
- Menambahkan laporan kemajuan proyek
|
||||
- Menyelesaikan atau membatalkan proyek
|
||||
|
||||
### 6. Manajemen Tugas
|
||||
- **Deskripsi**: Fitur untuk mengelola tugas-tugas dalam proyek atau divisi
|
||||
- **Dapat Diakses Oleh**: Super Admin, Admin Desa, Ketua Divisi, Leader Proyek
|
||||
- **Fungsi**:
|
||||
- Membuat tugas baru
|
||||
- Menetapkan anggota yang bertugas
|
||||
- Melacak kemajuan tugas
|
||||
- Menambahkan detail waktu pelaksanaan
|
||||
- Melampirkan dokumen terkait tugas
|
||||
|
||||
### 7. Divisi
|
||||
- **Deskripsi**: Fitur untuk membuat dan mengelola divisi-divisi dalam desa
|
||||
- **Dapat Diakses Oleh**: Super Admin, Admin Desa
|
||||
- **Fungsi**:
|
||||
- Membuat divisi baru
|
||||
- Mengelola anggota dalam divisi
|
||||
- Menetapkan admin dan leader divisi
|
||||
- Mengelola proyek yang dikelola oleh divisi
|
||||
- Mengelola diskusi internal divisi
|
||||
- Mengelola dokumentasi divisi
|
||||
- Mengelola kalender kegiatan divisi
|
||||
|
||||
### 8. Dokumentasi
|
||||
- **Deskripsi**: Fitur untuk penyimpanan dokumen terpusat dalam divisi
|
||||
- **Dapat Diakses Oleh**: Admin Divisi, Anggota Divisi (tergantung izin)
|
||||
- **Fungsi**:
|
||||
- Upload dokumen ke dalam folder
|
||||
- Membuat struktur folder
|
||||
- Berbagi dokumen antar divisi
|
||||
- Cut dan paste dokumen antar folder
|
||||
- Melihat riwayat dokumen
|
||||
|
||||
### 9. Kalender
|
||||
- **Deskripsi**: Fitur untuk mengelola jadwal kegiatan desa dan divisi
|
||||
- **Dapat Diakses Oleh**: Super Admin, Admin Desa, Ketua Divisi
|
||||
- **Fungsi**:
|
||||
- Membuat jadwal kegiatan baru
|
||||
- Mengatur pengingat kegiatan
|
||||
- Menetapkan peserta kegiatan
|
||||
- Mengelola kegiatan berulang
|
||||
- Melihat riwayat kegiatan
|
||||
|
||||
### 10. Tema Warna
|
||||
- **Deskripsi**: Fitur untuk mengelola tampilan warna aplikasi berdasarkan desa
|
||||
- **Dapat Diakses Oleh**: Super Admin, Admin Desa
|
||||
- **Fungsi**:
|
||||
- Mengatur warna utama aplikasi
|
||||
- Mengatur warna latar belakang
|
||||
- Mengatur warna elemen-elemen tampilan
|
||||
|
||||
### 11. Banner
|
||||
- **Deskripsi**: Fitur untuk mengelola banner tampilan utama aplikasi
|
||||
- **Dapat Diakses Oleh**: Super Admin, Admin Desa
|
||||
- **Fungsi**:
|
||||
- Upload banner baru
|
||||
- Mengatur tampilan banner
|
||||
- Menghapus banner lama
|
||||
|
||||
### 12. Notifikasi
|
||||
- **Deskripsi**: Fitur untuk mengelola dan menerima notifikasi dalam aplikasi
|
||||
- **Dapat Diakses Oleh**: Seluruh pengguna
|
||||
- **Fungsi**:
|
||||
- Menerima notifikasi real-time
|
||||
- Melihat riwayat notifikasi
|
||||
- Mengelola pengaturan notifikasi
|
||||
|
||||
## Cara Menggunakan Aplikasi
|
||||
|
||||
### 1. Login ke Sistem
|
||||
- Buka browser dan kunjungi alamat aplikasi
|
||||
- Masukkan NIK dan password yang telah didaftarkan
|
||||
- Klik tombol "Login"
|
||||
- Sistem akan mengarahkan ke dashboard sesuai dengan peran pengguna
|
||||
|
||||
### 2. Dashboard
|
||||
- Setelah login, Anda akan diarahkan ke halaman dashboard
|
||||
- Dashboard menampilkan ringkasan aktivitas dan informasi penting sesuai dengan hak akses Anda
|
||||
- Gunakan menu navigasi di sisi kiri untuk mengakses fitur-fitur lain
|
||||
|
||||
### 3. Melihat dan Membuat Pengumuman
|
||||
- **Melihat Pengumuman**:
|
||||
- Klik menu "Pengumuman" di sidebar
|
||||
- Pilih pengumuman yang ingin dibaca
|
||||
- Anda juga dapat mengunduh file terlampir jika ada
|
||||
|
||||
- **Membuat Pengumuman (Untuk Pengguna Berwenang)**:
|
||||
- Klik menu "Pengumuman" di sidebar
|
||||
- Klik tombol "Buat Pengumuman Baru"
|
||||
- Isi judul, deskripsi, dan pilih grup/divisi yang akan menerima
|
||||
- Lampirkan file jika diperlukan
|
||||
- Klik "Simpan" untuk menerbitkan pengumuman
|
||||
|
||||
### 4. Bergabung dalam Diskusi
|
||||
- **Diskusi Umum**:
|
||||
- Klik menu "Diskusi Umum" di sidebar
|
||||
- Pilih forum diskusi yang tersedia
|
||||
- Klik pada topik diskusi untuk membacanya
|
||||
- Tulis komentar Anda dan klik "Kirim"
|
||||
|
||||
- **Diskusi Divisi**:
|
||||
- Klik menu "Divisi" di sidebar
|
||||
- Pilih divisi yang Anda ikuti
|
||||
- Klik pada tab "Diskusi"
|
||||
- Ikuti proses diskusi seperti pada diskusi umum
|
||||
|
||||
### 5. Mengelola Proyek
|
||||
- Klik menu "Proyek" di sidebar
|
||||
- Untuk membuat proyek baru, klik "Tambah Proyek"
|
||||
- Isi informasi proyek seperti judul, deskripsi, tanggal mulai, dll.
|
||||
- Tambahkan anggota tim proyek
|
||||
- Buat tugas-tugas dalam proyek dan tetapkan ke anggota
|
||||
- Pantau kemajuan proyek secara real-time
|
||||
|
||||
### 6. Mengelola Divisi
|
||||
- Klik menu "Divisi" di sidebar
|
||||
- Untuk membuat divisi baru, klik "Tambah Divisi"
|
||||
- Isi informasi divisi seperti nama, deskripsi, dll.
|
||||
- Tambahkan anggota ke dalam divisi
|
||||
- Sebagai ketua divisi, Anda dapat menambahkan anggota
|
||||
- Tetapkan admin dan leader divisi
|
||||
- Kelola proyek, diskusi, dan dokumentasi dalam divisi
|
||||
|
||||
### 7. Mengelola Dokumen
|
||||
- Klik menu "Divisi" di sidebar
|
||||
- Pilih divisi yang Anda kelola atau ikuti
|
||||
- Klik pada tab "Dokumen"
|
||||
- Buat folder untuk mengorganisir dokumen
|
||||
- Upload dokumen dengan klik tombol "Upload"
|
||||
- Bagikan dokumen dengan divisi lain jika diperlukan
|
||||
|
||||
### 8. Menggunakan Kalender
|
||||
- Klik menu "Divisi" di sidebar
|
||||
- Pilih divisi yang Anda kelola atau ikuti
|
||||
- Klik pada tab "Kalender"
|
||||
- Lihat jadwal kegiatan yang telah direncanakan
|
||||
- Klik "Tambah Kegiatan" untuk membuat jadwal baru
|
||||
- Atur tanggal, waktu, dan pengingat untuk kegiatan
|
||||
|
||||
### 9. Mengelola Profil
|
||||
- Klik foto profil Anda di pojok kanan atas
|
||||
- Pilih "Profil" untuk melihat atau mengedit informasi pribadi
|
||||
- Ganti foto profil, password, atau informasi kontak
|
||||
|
||||
## Tips dan Trik
|
||||
|
||||
1. **Gunakan Fitur Pencarian**: Gunakan fitur pencarian untuk menemukan pengumuman, diskusi, atau dokumen secara cepat.
|
||||
|
||||
2. **Atur Notifikasi**: Sesuaikan pengaturan notifikasi agar hanya menerima informasi yang relevan dengan peran Anda.
|
||||
|
||||
3. **Gunakan Filter**: Gunakan filter untuk menampilkan data yang spesifik sesuai kebutuhan (misalnya proyek aktif, pengumuman terbaru, dll.).
|
||||
|
||||
4. **Organisasi Dokumen**: Buat folder yang terstruktur untuk mengorganisasi dokumen agar mudah dicari kembali.
|
||||
|
||||
5. **Update Informasi**: Pastikan informasi pribadi Anda selalu diperbarui agar komunikasi berjalan efektif.
|
||||
|
||||
6. **Gunakan Mobile Version**: Aplikasi ini responsif dan dapat digunakan di perangkat mobile untuk kemudahan akses.
|
||||
|
||||
7. **Ikuti Aturan Diskusi**: Hormati sesama pengguna saat berdiskusi dan gunakan bahasa yang sopan.
|
||||
|
||||
8. **Gunakan Kalender**: Manfaatkan fitur kalender untuk tidak ketinggalan kegiatan penting di desa.
|
||||
|
||||
9. **Laporan Masalah**: Jika menemui masalah teknis, laporkan segera kepada admin untuk ditindaklanjuti.
|
||||
|
||||
10. **Pelajari Fitur Lainnya**: Luangkan waktu untuk menjelajahi semua fitur yang tersedia agar dapat memanfaatkan aplikasi secara maksimal.
|
||||
204
QWEN.md
Normal file
204
QWEN.md
Normal file
@@ -0,0 +1,204 @@
|
||||
# Sistem Desa Mandiri - Project Documentation
|
||||
|
||||
## Project Overview
|
||||
|
||||
Sistem Desa Mandiri is a comprehensive web application built with Next.js to assist with village-level administration and information management. The application provides various features to support village activities, including announcements, discussions, project management, and population administration.
|
||||
|
||||
### Key Features
|
||||
- **User Management**: Manage member data and access rights
|
||||
- **Announcements**: Distribute important information to all village residents
|
||||
- **Discussions**: Forum for discussions among villagers or village officials
|
||||
- **Project & Task Management**: Track progress of ongoing village projects and tasks
|
||||
- **Documentation**: Centralized location for storing and managing important documents
|
||||
- **Push Notifications**: Send real-time notifications to user devices
|
||||
|
||||
### Technology Stack
|
||||
- **Framework**: Next.js 14
|
||||
- **UI Framework**: Mantine
|
||||
- **Database ORM**: Prisma
|
||||
- **Styling**: Tailwind CSS, CSS Modules
|
||||
- **State Management**: Hookstate
|
||||
- **Push Notifications**: Web Push
|
||||
- **Authentication**: Custom cookie-based authentication system
|
||||
- **Icons**: Tabler Icons React
|
||||
- **Rich Text Editor**: TipTap
|
||||
- **Charts**: Recharts, ECharts
|
||||
- **Date Handling**: Day.js, Moment.js
|
||||
- **File Upload**: Multer
|
||||
- **Server Framework**: Elysia.js
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
sistem-desa-mandiri/
|
||||
├── src/
|
||||
│ ├── app/ # Next.js app router pages
|
||||
│ │ ├── (application)/ # Main application routes
|
||||
│ │ ├── (auth)/ # Authentication routes
|
||||
│ │ ├── api/ # API routes
|
||||
│ │ └── ... # Other route groups
|
||||
│ ├── module/ # Feature modules organized by domain
|
||||
│ │ ├── _global/ # Global components and utilities
|
||||
│ │ ├── announcement/ # Announcement feature
|
||||
│ │ ├── auth/ # Authentication feature
|
||||
│ │ ├── discussion/ # Discussion forum
|
||||
│ │ ├── document/ # Document management
|
||||
│ │ ├── project/ # Project management
|
||||
│ │ ├── user/ # User management
|
||||
│ │ └── ... # Other feature modules
|
||||
│ ├── lib/ # Utility functions and libraries
|
||||
│ ├── types/ # TypeScript type definitions
|
||||
├── public/ # Static assets
|
||||
├── .env.test # Environment variables template
|
||||
├── next.config.mjs # Next.js configuration
|
||||
├── package.json # Dependencies and scripts
|
||||
├── README.md # Project documentation
|
||||
├── tailwind.config.ts # Tailwind CSS configuration
|
||||
└── tsconfig.json # TypeScript configuration
|
||||
```
|
||||
|
||||
### Module Organization
|
||||
The application follows a modular architecture where each feature is contained in its own module directory under `/src/module/`. Each module typically contains:
|
||||
- `api/` - API functions and server actions
|
||||
- `ui/` - User interface components
|
||||
- `hooks/` - Custom React hooks
|
||||
- `types/` - Type definitions specific to the module
|
||||
- `utils/` - Utility functions
|
||||
|
||||
## Building and Running
|
||||
|
||||
### Prerequisites
|
||||
- Node.js (version 20.x or higher)
|
||||
- Bun (recommended) or other package managers like npm/yarn/pnpm
|
||||
- Database (PostgreSQL, MySQL, or SQLite)
|
||||
|
||||
### Installation Steps
|
||||
1. Clone the repository:
|
||||
```bash
|
||||
git clone https://github.com/username/sistem-desa-mandiri.git
|
||||
cd sistem-desa-mandiri
|
||||
```
|
||||
|
||||
2. Install dependencies:
|
||||
```bash
|
||||
bun install
|
||||
```
|
||||
|
||||
3. Setup environment variables:
|
||||
```bash
|
||||
cp .env.test .env
|
||||
```
|
||||
Edit the `.env` file and fill in the required variables, especially `DATABASE_URL`.
|
||||
|
||||
4. Run Prisma migrations:
|
||||
```bash
|
||||
npx prisma migrate dev
|
||||
```
|
||||
|
||||
5. Seed the database (optional):
|
||||
```bash
|
||||
npx prisma db seed
|
||||
```
|
||||
|
||||
6. Run the development server:
|
||||
```bash
|
||||
bun run dev
|
||||
```
|
||||
The application will run at https://localhost:3000
|
||||
|
||||
### Available Scripts
|
||||
- `dev`: Runs the development server with HTTPS
|
||||
- `build`: Creates a production build of the application
|
||||
- `start`: Runs the production server
|
||||
- `lint`: Runs the linter to check code quality
|
||||
- `prisma:seed`: Runs the database seeding script
|
||||
|
||||
## Development Conventions
|
||||
|
||||
### Coding Standards
|
||||
- Follow Next.js conventions for file-based routing
|
||||
- Use TypeScript for type safety
|
||||
- Maintain consistent component structure within modules
|
||||
- Use Mantine components for UI elements
|
||||
- Follow accessibility best practices
|
||||
|
||||
### Naming Conventions
|
||||
- Components: PascalCase (e.g., `UserProfile.tsx`)
|
||||
- Functions: camelCase (e.g., `getUserData`)
|
||||
- Constants: UPPER_SNAKE_CASE (e.g., `MAX_FILE_SIZE`)
|
||||
- Modules: lowercase with hyphens if needed (e.g., `discussion-general`)
|
||||
|
||||
### State Management
|
||||
- Use Hookstate for global state management
|
||||
- Use React hooks for component-local state
|
||||
- Store persistent data in cookies or localStorage as appropriate
|
||||
|
||||
### API Design
|
||||
- Organize API routes by feature in the `/src/app/api/` directory
|
||||
- Use RESTful conventions where possible
|
||||
- Implement proper error handling and validation
|
||||
- Secure endpoints with appropriate authentication checks
|
||||
|
||||
### Testing
|
||||
- Unit tests should be co-located with the code they test
|
||||
- Integration tests should be in the `/tests/` directory
|
||||
- Follow the testing pyramid: many unit tests, fewer integration tests, minimal end-to-end tests
|
||||
|
||||
## Key Dependencies
|
||||
|
||||
### Core Dependencies
|
||||
- `next`: React framework for production applications
|
||||
- `react`, `react-dom`: UI library
|
||||
- `@mantine/core`: Component library with accessible components
|
||||
- `@prisma/client`: Database toolkit
|
||||
- `web-push`: Web Push protocol implementation
|
||||
- `elysia`: Fast, lightweight web framework
|
||||
- `@hookstate/core`: State management solution
|
||||
|
||||
### UI Dependencies
|
||||
- `@mantine/carousel`: Carousel component
|
||||
- `@mantine/charts`: Chart components
|
||||
- `@mantine/form`: Form management
|
||||
- `@mantine/notifications`: Notification system
|
||||
- `@mantine/tiptap`: Rich text editor components
|
||||
- `@tabler/icons-react`: Icon library
|
||||
- `@tiptap/react`: Rich text editor
|
||||
- `recharts`: Charting library
|
||||
- `echarts-for-react`: Alternative charting library
|
||||
|
||||
### Utilities
|
||||
- `dayjs`: Date manipulation library
|
||||
- `lodash`: Utility functions
|
||||
- `crypto-js`: Cryptographic algorithms
|
||||
- `iron-session`: Session management
|
||||
- `jose`: JavaScript Object Signing and Encryption
|
||||
- `multer`: File upload middleware
|
||||
- `firebase-admin`: Firebase admin SDK
|
||||
|
||||
## Architecture Patterns
|
||||
|
||||
### Modular Design
|
||||
The application follows a modular design where each feature is encapsulated in its own module directory. This promotes separation of concerns and makes the codebase easier to maintain and scale.
|
||||
|
||||
### API Layer
|
||||
API routes are organized by feature in the `/src/app/api/` directory. Each feature has its own subdirectory containing related API endpoints. This makes it easy to locate and maintain API functionality.
|
||||
|
||||
### Component Organization
|
||||
Components are organized within their respective module directories. Common components that are shared across multiple modules are placed in the `_global` module.
|
||||
|
||||
### Data Flow
|
||||
- Client-side state is managed using React hooks and Hookstate
|
||||
- Server-side data fetching is done through Next.js API routes
|
||||
- Database interactions are handled through Prisma ORM
|
||||
- Authentication is implemented using cookies and server actions
|
||||
|
||||
## Deployment
|
||||
|
||||
The application is designed to be deployed as a Next.js application. It can be deployed to platforms like Vercel, Netlify, or any hosting service that supports Node.js applications.
|
||||
|
||||
For production deployment:
|
||||
1. Run `bun run build` to create an optimized production build
|
||||
2. Run `bun start` to start the production server
|
||||
3. Configure environment variables for the production environment
|
||||
4. Set up SSL certificates for secure connections
|
||||
5. Configure database connection for production environment
|
||||
@@ -172,16 +172,16 @@ model Announcement {
|
||||
}
|
||||
|
||||
model AnnouncementMember {
|
||||
id String @id @default(cuid())
|
||||
Announcement Announcement @relation(fields: [idAnnouncement], references: [id])
|
||||
idAnnouncement String
|
||||
Group Group @relation(fields: [idGroup], references: [id])
|
||||
idGroup String
|
||||
Division Division @relation(fields: [idDivision], references: [id])
|
||||
idDivision String
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
id String @id @default(cuid())
|
||||
Announcement Announcement @relation(fields: [idAnnouncement], references: [id])
|
||||
idAnnouncement String
|
||||
Group Group @relation(fields: [idGroup], references: [id])
|
||||
idGroup String
|
||||
Division Division @relation(fields: [idDivision], references: [id])
|
||||
idDivision String
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model AnnouncementFile {
|
||||
@@ -423,6 +423,7 @@ model DivisionDisscussion {
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
DivisionDisscussionComment DivisionDisscussionComment[]
|
||||
DivisionDiscussionFile DivisionDiscussionFile[]
|
||||
}
|
||||
|
||||
model DivisionDisscussionComment {
|
||||
@@ -437,6 +438,17 @@ model DivisionDisscussionComment {
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
model DivisionDiscussionFile {
|
||||
id String @id @default(cuid())
|
||||
DivisionDisscussion DivisionDisscussion @relation(fields: [idDiscussion], references: [id])
|
||||
idDiscussion String
|
||||
name String
|
||||
extension String
|
||||
idStorage String?
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model DivisionDocumentFolderFile {
|
||||
id String @id @default(cuid())
|
||||
@@ -608,6 +620,7 @@ model Discussion {
|
||||
updatedAt DateTime @updatedAt
|
||||
DiscussionMember DiscussionMember[]
|
||||
DiscussionComment DiscussionComment[]
|
||||
DiscussionFile DiscussionFile[]
|
||||
}
|
||||
|
||||
model DiscussionMember {
|
||||
@@ -633,3 +646,15 @@ model DiscussionComment {
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model DiscussionFile {
|
||||
id String @id @default(cuid())
|
||||
Discussion Discussion @relation(fields: [idDiscussion], references: [id])
|
||||
idDiscussion String
|
||||
name String
|
||||
extension String
|
||||
idStorage String?
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
213
prisma/seed.ts
213
prisma/seed.ts
@@ -1,7 +1,11 @@
|
||||
import { seederAdmin, seederAdminRole, seederDesa, seederGroup, seederPosition, seederTheme, seederUser, seederUserRole } from '@/module/seeder';
|
||||
import { seederAdmin, seederAdminRole, seederAnnouncement, seederAnnouncementMember, seederDesa, seederDiscussion, seederDiscussionMember, seederDivision, seederDivisionMember, seederGroup, seederPosition, seederProject, seederProjectMember, seederProjectTask, seederTheme, seederUser, seederUserRole } from '@/module/seeder';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
// DATA YG DI SEEDER MERUPAKAN DATA REAL(DARMASABA) & DATA DUMMY (MANDALA)
|
||||
// DATA JSON GABUNGAN (REAL & DUMMY) ADALAH adminRole, admin, theme, desa, group, position, user, userRole, user
|
||||
// Selain table yg disebutkan, data lainnya merupakan data dummy
|
||||
|
||||
async function main() {
|
||||
// ADMIN ROLE
|
||||
for (let data of seederAdminRole) {
|
||||
@@ -144,7 +148,7 @@ async function main() {
|
||||
})
|
||||
}
|
||||
|
||||
// USER
|
||||
// USER
|
||||
for (let data of seederUser) {
|
||||
await prisma.user.upsert({
|
||||
where: {
|
||||
@@ -176,6 +180,211 @@ async function main() {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// DISCUSSION
|
||||
for (let data of seederDiscussion) {
|
||||
await prisma.discussion.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
idVillage: data.idVillage,
|
||||
idGroup: data.idGroup,
|
||||
title: data.title,
|
||||
desc: data.desc,
|
||||
status: data.status,
|
||||
createdBy: data.createdBy
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
idVillage: data.idVillage,
|
||||
idGroup: data.idGroup,
|
||||
title: data.title,
|
||||
desc: data.desc,
|
||||
status: data.status,
|
||||
createdBy: data.createdBy
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// DISSCUSSION MEMBER
|
||||
for (let data of seederDiscussionMember) {
|
||||
await prisma.discussionMember.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
idDiscussion: data.idDiscussion,
|
||||
idUser: data.idUser
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
idDiscussion: data.idDiscussion,
|
||||
idUser: data.idUser
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// PROJECT
|
||||
for (let data of seederProject) {
|
||||
await prisma.project.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
idVillage: data.idVillage,
|
||||
idGroup: data.idGroup,
|
||||
title: data.title,
|
||||
desc: data.desc,
|
||||
status: data.status,
|
||||
createdBy: data.createdBy
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
idVillage: data.idVillage,
|
||||
idGroup: data.idGroup,
|
||||
title: data.title,
|
||||
desc: data.desc,
|
||||
status: data.status,
|
||||
createdBy: data.createdBy
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// PROJECT MEMBER
|
||||
for (let data of seederProjectMember) {
|
||||
await prisma.projectMember.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
idProject: data.idProject,
|
||||
idUser: data.idUser,
|
||||
isLeader: data.isLeader
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
idProject: data.idProject,
|
||||
idUser: data.idUser,
|
||||
isLeader: data.isLeader
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// PROJECT TASK
|
||||
for (let data of seederProjectTask) {
|
||||
await prisma.projectTask.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
idProject: data.idProject,
|
||||
title: data.title,
|
||||
desc: data.desc,
|
||||
status: data.status,
|
||||
dateStart: new Date(data.dateStart),
|
||||
dateEnd: new Date(data.dateEnd)
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
idProject: data.idProject,
|
||||
title: data.title,
|
||||
desc: data.desc,
|
||||
status: data.status,
|
||||
dateStart: new Date(data.dateStart),
|
||||
dateEnd: new Date(data.dateEnd)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// DIVISION
|
||||
for (let data of seederDivision) {
|
||||
await prisma.division.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
name: data.name,
|
||||
desc: data.desc,
|
||||
createdBy: data.createdBy
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
idVillage: data.idVillage,
|
||||
idGroup: data.idGroup,
|
||||
name: data.name,
|
||||
desc: data.desc,
|
||||
createdBy: data.createdBy,
|
||||
isActive: true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// DIVISION MEMBER
|
||||
for (let data of seederDivisionMember) {
|
||||
await prisma.divisionMember.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
idUser: data.idUser,
|
||||
isAdmin: data.isAdmin,
|
||||
isLeader: data.isLeader
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
idDivision: data.idDivision,
|
||||
idUser: data.idUser,
|
||||
isAdmin: data.isAdmin,
|
||||
isLeader: data.isLeader,
|
||||
isActive: true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// ANNOUNCEMENT
|
||||
for (let data of seederAnnouncement) {
|
||||
await prisma.announcement.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
title: data.title,
|
||||
desc: data.desc,
|
||||
createdBy: data.createdBy
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
idVillage: data.idVillage,
|
||||
title: data.title,
|
||||
desc: data.desc,
|
||||
createdBy: data.createdBy,
|
||||
isActive: true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// ANNOUNCEMENT MEMBER
|
||||
for (let data of seederAnnouncementMember) {
|
||||
await prisma.announcementMember.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
idAnnouncement: data.idAnnouncement,
|
||||
idGroup: data.idGroup,
|
||||
idDivision: data.idDivision
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
idAnnouncement: data.idAnnouncement,
|
||||
idGroup: data.idGroup,
|
||||
idDivision: data.idDivision,
|
||||
isActive: true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
main().then(async () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { countTime, prisma } from "@/module/_global";
|
||||
import { countTime, DIR, funUploadFile, prisma } from "@/module/_global";
|
||||
import { funGetUserById } from "@/module/auth";
|
||||
import { createLogUserMobile } from "@/module/user";
|
||||
import _ from "lodash";
|
||||
@@ -8,7 +8,7 @@ import { NextResponse } from "next/server";
|
||||
|
||||
|
||||
// GET ONE DETAIL DISKUSI UMUM
|
||||
export async function GET(request : Request, context: { params: { id: string } }) {
|
||||
export async function GET(request: Request, context: { params: { id: string } }) {
|
||||
try {
|
||||
let dataFix
|
||||
const { id } = context.params
|
||||
@@ -127,8 +127,21 @@ export async function GET(request : Request, context: { params: { id: string } }
|
||||
} else {
|
||||
dataFix = false
|
||||
}
|
||||
}
|
||||
} else if (kategori == "file") {
|
||||
const data = await prisma.discussionFile.findMany({
|
||||
where: {
|
||||
idDiscussion: id
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
idStorage: true,
|
||||
name: true,
|
||||
extension: true
|
||||
}
|
||||
})
|
||||
|
||||
dataFix = data
|
||||
}
|
||||
|
||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan diskusi", data: dataFix }, { status: 200 });
|
||||
|
||||
@@ -247,7 +260,12 @@ export async function DELETE(request: Request, context: { params: { id: string }
|
||||
export async function PUT(request: Request, context: { params: { id: string } }) {
|
||||
try {
|
||||
const { id } = context.params
|
||||
const { title, desc, user } = (await request.json());
|
||||
const body = await request.formData()
|
||||
const dataBody = body.get("data")
|
||||
const cekFile = body.has("file0")
|
||||
|
||||
// const { title, desc, user } = (await request.json());
|
||||
const { title, desc, user, oldFile } = JSON.parse(dataBody as string)
|
||||
|
||||
const userMobile = await funGetUserById({ id: String(user) })
|
||||
|
||||
@@ -275,6 +293,41 @@ export async function PUT(request: Request, context: { params: { id: string } })
|
||||
}
|
||||
});
|
||||
|
||||
if (oldFile.length > 0) {
|
||||
for (let index = 0; index < oldFile.length; index++) {
|
||||
const element = oldFile[index];
|
||||
if (element.delete) {
|
||||
await prisma.discussionFile.delete({
|
||||
where: {
|
||||
id: element.id
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cekFile) {
|
||||
body.delete("data")
|
||||
for (var pair of body.entries()) {
|
||||
if (String(pair[0]).substring(0, 4) == "file") {
|
||||
const file = body.get(pair[0]) as File
|
||||
const fExt = file.name.split(".").pop()
|
||||
const fName = decodeURIComponent(file.name.replace("." + fExt, ""))
|
||||
const upload = await funUploadFile({ file: file, dirId: DIR.discussion })
|
||||
if (upload.success) {
|
||||
await prisma.discussionFile.create({
|
||||
data: {
|
||||
idStorage: upload.data.id,
|
||||
idDiscussion: id,
|
||||
name: fName,
|
||||
extension: String(fExt)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create log user
|
||||
const log = await createLogUserMobile({ act: 'UPDATE', desc: 'User mengupdate data diskusi umum', table: 'discussion', data: id, user: userMobile.id })
|
||||
return NextResponse.json({ success: true, message: "Berhasil mengedit diskusi umum" }, { status: 200 });
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { prisma } from "@/module/_global";
|
||||
import { DIR, funUploadFile, prisma } from "@/module/_global";
|
||||
import { funGetUserById } from "@/module/auth";
|
||||
import { createLogUserMobile } from "@/module/user";
|
||||
import _ from "lodash";
|
||||
@@ -112,13 +112,20 @@ export async function GET(request: Request) {
|
||||
// CREATE DISCUSSION GENERALE
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const { idGroup, user, title, desc, member } = await request.json();
|
||||
|
||||
if (user == "null" || user == undefined || user == "") {
|
||||
const body = await request.formData()
|
||||
const dataBody = body.get("data")
|
||||
const cekFile = body.has("file0")
|
||||
|
||||
// const { idGroup, user, title, desc, member } = await request.json();
|
||||
const { idGroup, user, title, desc, member } = JSON.parse(dataBody as string)
|
||||
|
||||
const userMobile = await funGetUserById({ id: user })
|
||||
|
||||
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
|
||||
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
|
||||
}
|
||||
|
||||
const userMobile = await funGetUserById({ id: user })
|
||||
const userId = user
|
||||
const userRoleLogin = userMobile.idUserRole
|
||||
|
||||
@@ -145,6 +152,29 @@ export async function POST(request: Request) {
|
||||
data: dataMember
|
||||
})
|
||||
|
||||
|
||||
if (cekFile) {
|
||||
body.delete("data")
|
||||
for (var pair of body.entries()) {
|
||||
if (String(pair[0]).substring(0, 4) == "file") {
|
||||
const file = body.get(pair[0]) as File
|
||||
const fExt = file.name.split(".").pop()
|
||||
const fName = decodeURIComponent(file.name.replace("." + fExt, ""))
|
||||
const upload = await funUploadFile({ file: file, dirId: DIR.discussion })
|
||||
if (upload.success) {
|
||||
await prisma.discussionFile.create({
|
||||
data: {
|
||||
idStorage: upload.data.id,
|
||||
idDiscussion: data.id,
|
||||
name: fName,
|
||||
extension: String(fExt)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const memberNotifMobile = await prisma.discussionMember.findMany({
|
||||
where: {
|
||||
idDiscussion: data.id
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { countTime, prisma } from "@/module/_global";
|
||||
import { countTime, DIR, funUploadFile, prisma } from "@/module/_global";
|
||||
import { funGetUserById } from "@/module/auth";
|
||||
import { createLogUserMobile } from "@/module/user";
|
||||
import _ from "lodash";
|
||||
@@ -70,6 +70,21 @@ export async function GET(request: Request, context: { params: { id: string } })
|
||||
}))
|
||||
|
||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan komentar", data: omitMember }, { status: 200 });
|
||||
} else if (cat == "file") {
|
||||
const data = await prisma.divisionDiscussionFile.findMany({
|
||||
where: {
|
||||
idDiscussion: id,
|
||||
isActive: true
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
idStorage: true,
|
||||
name: true,
|
||||
extension: true
|
||||
}
|
||||
})
|
||||
|
||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan file", data: data }, { status: 200 });
|
||||
} else {
|
||||
const data = await prisma.divisionDisscussion.findUnique({
|
||||
where: {
|
||||
@@ -212,7 +227,13 @@ export async function PUT(request: Request, context: { params: { id: string } })
|
||||
export async function POST(request: Request, context: { params: { id: string } }) {
|
||||
try {
|
||||
const { id } = context.params
|
||||
const { title, desc, user } = (await request.json())
|
||||
const body = await request.formData()
|
||||
const dataBody = body.get("data")
|
||||
const cekFile = body.has("file0")
|
||||
|
||||
// const { title, desc, user } = (await request.json())
|
||||
const { title, desc, user, oldFile } = JSON.parse(dataBody as string)
|
||||
|
||||
|
||||
const userMobile = await funGetUserById({ id: String(user) })
|
||||
|
||||
@@ -239,6 +260,41 @@ export async function POST(request: Request, context: { params: { id: string } }
|
||||
}
|
||||
});
|
||||
|
||||
if (oldFile.length > 0) {
|
||||
for (let index = 0; index < oldFile.length; index++) {
|
||||
const element = oldFile[index];
|
||||
if (element.delete) {
|
||||
await prisma.divisionDiscussionFile.delete({
|
||||
where: {
|
||||
id: element.id
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cekFile) {
|
||||
body.delete("data")
|
||||
for (var pair of body.entries()) {
|
||||
if (String(pair[0]).substring(0, 4) == "file") {
|
||||
const file = body.get(pair[0]) as File
|
||||
const fExt = file.name.split(".").pop()
|
||||
const fName = decodeURIComponent(file.name.replace("." + fExt, ""))
|
||||
const upload = await funUploadFile({ file: file, dirId: DIR.discussionDivision })
|
||||
if (upload.success) {
|
||||
await prisma.divisionDiscussionFile.create({
|
||||
data: {
|
||||
idStorage: upload.data.id,
|
||||
idDiscussion: id,
|
||||
name: fName,
|
||||
extension: String(fExt)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create log user
|
||||
const log = await createLogUserMobile({ act: 'UPDATE', desc: 'User mengupdate data diskusi', table: 'divisionDisscussion', data: id, user: userMobile.id })
|
||||
return NextResponse.json({ success: true, message: "Berhasil mengedit diskusi" }, { status: 200 });
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { funSendWebPush, prisma } from "@/module/_global";
|
||||
import { DIR, funSendWebPush, funUploadFile, prisma } from "@/module/_global";
|
||||
import { funGetUserById } from "@/module/auth";
|
||||
import { createLogUserMobile } from "@/module/user";
|
||||
import _ from "lodash";
|
||||
@@ -102,7 +102,14 @@ export async function GET(request: Request) {
|
||||
// CREATE DISCUSSION
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const { idDivision, desc, user } = (await request.json());
|
||||
const body = await request.formData()
|
||||
const dataBody = body.get("data")
|
||||
const cekFile = body.has("file0")
|
||||
|
||||
// const { idDivision, desc, user } = (await request.json());
|
||||
const { idDivision, desc, user } = JSON.parse(String(dataBody));
|
||||
|
||||
|
||||
const userMobile = await funGetUserById({ id: String(user) })
|
||||
|
||||
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
|
||||
@@ -135,6 +142,29 @@ export async function POST(request: Request) {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (cekFile) {
|
||||
body.delete("data")
|
||||
for (var pair of body.entries()) {
|
||||
if (String(pair[0]).substring(0, 4) == "file") {
|
||||
const file = body.get(pair[0]) as File
|
||||
const fExt = file.name.split(".").pop()
|
||||
const fName = decodeURIComponent(file.name.replace("." + fExt, ""))
|
||||
const upload = await funUploadFile({ file: file, dirId: DIR.discussionDivision })
|
||||
if (upload.success) {
|
||||
await prisma.divisionDiscussionFile.create({
|
||||
data: {
|
||||
idStorage: upload.data.id,
|
||||
idDiscussion: data.id,
|
||||
name: fName,
|
||||
extension: String(fExt)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const memberDivision = await prisma.divisionMember.findMany({
|
||||
where: {
|
||||
idDivision: idDivision
|
||||
|
||||
@@ -33,13 +33,21 @@ export async function GET(request: Request, context: { params: { id: string } })
|
||||
}
|
||||
|
||||
if (kategori == "jumlah") {
|
||||
const tahunFilter = new Date().getFullYear().toString();
|
||||
const startTahun = new Date(`${tahunFilter}-01-01T00:00:00.000Z`);
|
||||
const endTahun = new Date(`${parseInt(tahunFilter) + 1}-01-01T00:00:00.000Z`);
|
||||
|
||||
const tugas = await prisma.divisionProject.count({
|
||||
where: {
|
||||
idDivision: String(id),
|
||||
status: {
|
||||
lte: 1
|
||||
},
|
||||
isActive: true
|
||||
isActive: true,
|
||||
createdAt: {
|
||||
gte: startTahun,
|
||||
lt: endTahun
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ export async function GET(request: Request) {
|
||||
const name = searchParams.get('search');
|
||||
const status = searchParams.get('status');
|
||||
const idGroup = searchParams.get("group");
|
||||
const tahun = searchParams.get("year");
|
||||
const page = searchParams.get('page');
|
||||
const kategori = searchParams.get('cat');
|
||||
const user = searchParams.get('user');
|
||||
@@ -25,7 +26,7 @@ export async function GET(request: Request) {
|
||||
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
|
||||
}
|
||||
|
||||
let grup
|
||||
let grup, tahunFilter = String(tahun)
|
||||
const dataSkip = Number(page) * 10 - 10;
|
||||
const roleUser = userMobile.idUserRole
|
||||
const villageId = userMobile.idVillage
|
||||
@@ -37,6 +38,14 @@ export async function GET(request: Request) {
|
||||
grup = idGroup
|
||||
}
|
||||
|
||||
if (tahun == "null" || tahun == undefined || tahun == "" || tahun == "undefined") {
|
||||
tahunFilter = new Date().getFullYear().toString();
|
||||
}
|
||||
|
||||
const startTahun = new Date(`${tahunFilter}-01-01T00:00:00.000Z`);
|
||||
const endTahun = new Date(`${parseInt(tahunFilter) + 1}-01-01T00:00:00.000Z`);
|
||||
|
||||
|
||||
const cek = await prisma.group.count({
|
||||
where: {
|
||||
id: grup,
|
||||
@@ -58,7 +67,11 @@ export async function GET(request: Request) {
|
||||
contains: (name == undefined || name == "null") ? "" : name,
|
||||
mode: "insensitive"
|
||||
},
|
||||
status: (status == "0" || status == "1" || status == "2" || status == "3") ? Number(status) : 0
|
||||
status: (status == "0" || status == "1" || status == "2" || status == "3") ? Number(status) : 0,
|
||||
createdAt: {
|
||||
gte: startTahun,
|
||||
lt: endTahun
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +91,10 @@ export async function GET(request: Request) {
|
||||
some: {
|
||||
idUser: String(userId)
|
||||
}
|
||||
},
|
||||
createdAt: {
|
||||
gte: startTahun,
|
||||
lt: endTahun
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,7 +156,7 @@ export async function GET(request: Request) {
|
||||
})
|
||||
|
||||
|
||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan kegiatan", data: omitData, filter, total: totalData }, { status: 200 });
|
||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan kegiatan", data: omitData, filter, tahun: tahunFilter, total: totalData }, { status: 200 });
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
|
||||
46
src/app/api/mobile/project/tahun/route.ts
Normal file
46
src/app/api/mobile/project/tahun/route.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { prisma } from "@/module/_global";
|
||||
import { funGetUserById } from "@/module/auth";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const user = searchParams.get('user');
|
||||
const userMobile = await funGetUserById({ id: String(user) })
|
||||
|
||||
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
|
||||
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
|
||||
}
|
||||
|
||||
const villageId = userMobile.idVillage
|
||||
const currentYear = new Date().getFullYear();
|
||||
|
||||
const data = await prisma.project.findMany({
|
||||
where: {
|
||||
isActive: true,
|
||||
idVillage: villageId,
|
||||
},
|
||||
select: {
|
||||
createdAt: true,
|
||||
},
|
||||
})
|
||||
|
||||
const dataYear = data.map((item: any) => item.createdAt.getFullYear())
|
||||
// Hapus duplikat pakai Set
|
||||
const uniqueYears = [...new Set(dataYear)];
|
||||
|
||||
// Tambahkan tahun sekarang kalau belum ada
|
||||
if (!uniqueYears.includes(currentYear)) {
|
||||
uniqueYears.push(currentYear);
|
||||
}
|
||||
|
||||
// (opsional) urutkan dari terbaru ke lama
|
||||
uniqueYears.sort((a, b) => b - a);
|
||||
|
||||
const formattedData = uniqueYears.map(year => ({
|
||||
id: String(year),
|
||||
name: String(year)
|
||||
}));
|
||||
|
||||
return NextResponse.json({ success: true, message: "Success", data: formattedData }, { status: 200 });
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ export async function GET(request: Request) {
|
||||
const page = searchParams.get('page');
|
||||
const user = searchParams.get('user');
|
||||
const dataSkip = Number(page) * 10 - 10;
|
||||
const tahun = searchParams.get("year");
|
||||
|
||||
const userMobile = await funGetUserById({ id: String(user) })
|
||||
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
|
||||
@@ -33,6 +34,15 @@ export async function GET(request: Request) {
|
||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, data tidak ditemukan", }, { status: 200 });
|
||||
}
|
||||
|
||||
let tahunFilter = String(tahun)
|
||||
if (tahunFilter == "null" || tahunFilter == undefined || tahunFilter == "" || tahunFilter == "undefined") {
|
||||
tahunFilter = new Date().getFullYear().toString();
|
||||
}
|
||||
|
||||
|
||||
const startTahun = new Date(`${tahunFilter}-01-01T00:00:00.000Z`);
|
||||
const endTahun = new Date(`${parseInt(tahunFilter) + 1}-01-01T00:00:00.000Z`);
|
||||
|
||||
const data = await prisma.divisionProject.findMany({
|
||||
skip: dataSkip,
|
||||
take: 10,
|
||||
@@ -43,6 +53,10 @@ export async function GET(request: Request) {
|
||||
title: {
|
||||
contains: (name == undefined || name == "null") ? "" : name,
|
||||
mode: "insensitive"
|
||||
},
|
||||
createdAt: {
|
||||
gte: startTahun,
|
||||
lt: endTahun
|
||||
}
|
||||
},
|
||||
select: {
|
||||
@@ -87,11 +101,15 @@ export async function GET(request: Request) {
|
||||
title: {
|
||||
contains: (name == undefined || name == "null") ? "" : name,
|
||||
mode: "insensitive"
|
||||
},
|
||||
createdAt: {
|
||||
gte: startTahun,
|
||||
lt: endTahun
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan divisi", data: formatData, total: totalData }, { status: 200 });
|
||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan divisi", data: formatData, tahun: tahunFilter, total: totalData }, { status: 200 });
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
|
||||
47
src/app/api/mobile/task/tahun/route.ts
Normal file
47
src/app/api/mobile/task/tahun/route.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { prisma } from "@/module/_global";
|
||||
import { funGetUserById } from "@/module/auth";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const user = searchParams.get('user');
|
||||
const divisi = searchParams.get('division');
|
||||
const userMobile = await funGetUserById({ id: String(user) })
|
||||
const currentYear = new Date().getFullYear();
|
||||
|
||||
if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") {
|
||||
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 });
|
||||
}
|
||||
|
||||
const data = await prisma.divisionProject.findMany({
|
||||
where: {
|
||||
isActive: true,
|
||||
idDivision: String(divisi),
|
||||
},
|
||||
select: {
|
||||
createdAt: true,
|
||||
},
|
||||
})
|
||||
|
||||
const dataYear = data.map((item: any) => item.createdAt.getFullYear())
|
||||
// Hapus duplikat pakai Set
|
||||
const uniqueYears = [...new Set(dataYear)];
|
||||
|
||||
// Tambahkan tahun sekarang kalau belum ada
|
||||
if (!uniqueYears.includes(currentYear)) {
|
||||
uniqueYears.push(currentYear);
|
||||
}
|
||||
|
||||
// (opsional) urutkan dari terbaru ke lama
|
||||
uniqueYears.sort((a, b) => b - a);
|
||||
|
||||
const formattedData = uniqueYears.map(year => ({
|
||||
id: String(year),
|
||||
name: String(year)
|
||||
}));
|
||||
|
||||
|
||||
|
||||
return NextResponse.json({ success: true, message: "Success", data: formattedData }, { status: 200 });
|
||||
|
||||
}
|
||||
@@ -12,7 +12,9 @@ export const DIR = {
|
||||
village: "cm0xhb91o0007acbbkx8rk8hj",
|
||||
user: "cm0x8dbwn0005bp5tgmfcthzw",
|
||||
banner: "cm1sxex19004938bjvyaq8vta",
|
||||
announcement: "cmkdfkze4005hkhjgunsroi4t"
|
||||
announcement: "cmkdfkze4005hkhjgunsroi4t",
|
||||
discussion: "cmkf5h7ic006jkhjgyrkog7ut",
|
||||
discussionDivision: "cmkdfktfm005fkhjggjvnqly5"
|
||||
}
|
||||
|
||||
export const keyWibu = 'padahariminggukuturutayahkekotanaikdelmanistimewakududukdimuka'
|
||||
|
||||
922
src/module/seeder/complete_village_seeder.ts
Normal file
922
src/module/seeder/complete_village_seeder.ts
Normal file
@@ -0,0 +1,922 @@
|
||||
import { prisma } from "@/module/_global";
|
||||
import {
|
||||
seederAdmin,
|
||||
seederAdminRole,
|
||||
seederDesa,
|
||||
seederGroup,
|
||||
seederPosition,
|
||||
seederTheme,
|
||||
seederUser,
|
||||
seederUserRole
|
||||
} from '@/module/seeder';
|
||||
|
||||
async function seedCompleteVillageData() {
|
||||
console.log("Starting complete village data seeding process...");
|
||||
|
||||
// Define comprehensive dummy data variables outside transaction scope
|
||||
// GROUP - Comprehensive dummy data
|
||||
const seederGroupComprehensive = [
|
||||
{
|
||||
"id": "group_rt01",
|
||||
"idVillage": "desaDummy",
|
||||
"name": "Dinas"
|
||||
},
|
||||
{
|
||||
"id": "group_rt02",
|
||||
"idVillage": "desaDummy",
|
||||
"name": "Adat"
|
||||
},
|
||||
{
|
||||
"id": "group_karang_taruna",
|
||||
"idVillage": "desaDummy",
|
||||
"name": "Karang Taruna"
|
||||
},
|
||||
{
|
||||
"id": "group_bumdes",
|
||||
"idVillage": "desaDummy",
|
||||
"name": "PKK"
|
||||
}
|
||||
];
|
||||
|
||||
// POSITION - Comprehensive dummy data
|
||||
const seederPositionComprehensive = [
|
||||
{
|
||||
"id": "pos_ketua_rt01",
|
||||
"idGroup": "group_rt01",
|
||||
"name": "Perbekel"
|
||||
},
|
||||
{
|
||||
"id": "pos_sekretaris_rt01",
|
||||
"idGroup": "group_rt01",
|
||||
"name": "Sekretaris"
|
||||
},
|
||||
{
|
||||
"id": "pos_bendahara_rt01",
|
||||
"idGroup": "group_rt01",
|
||||
"name": "Bendahara"
|
||||
},
|
||||
{
|
||||
"id": "pos_staff_rt01",
|
||||
"idGroup": "group_rt01",
|
||||
"name": "Staff"
|
||||
},
|
||||
{
|
||||
"id": "pos_staff_rt02",
|
||||
"idGroup": "group_rt02",
|
||||
"name": "Staff"
|
||||
},
|
||||
{
|
||||
"id": "pos_ketua_karang_taruna",
|
||||
"idGroup": "group_karang_taruna",
|
||||
"name": "Ketua Karang Taruna"
|
||||
},
|
||||
{
|
||||
"id": "pos_ketua_bumdes",
|
||||
"idGroup": "group_bumdes",
|
||||
"name": "Ketua PKK"
|
||||
}
|
||||
];
|
||||
|
||||
// USER - Comprehensive dummy data
|
||||
const seederUserComprehensive = [
|
||||
{
|
||||
"id": "user_kades",
|
||||
"idUserRole": "supadmin",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_rt01",
|
||||
"idPosition": "pos_ketua_rt01",
|
||||
"nik": "3201010101010001",
|
||||
"name": "Kepala Desa",
|
||||
"phone": "081234567890",
|
||||
"email": "kades@desamandiri.test",
|
||||
"gender": "M"
|
||||
},
|
||||
{
|
||||
"id": "user_sekdes",
|
||||
"idUserRole": "admin",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_rt01",
|
||||
"idPosition": "pos_sekretaris_rt01",
|
||||
"nik": "3201010101010002",
|
||||
"name": "Sekretaris Desa",
|
||||
"phone": "081234567891",
|
||||
"email": "sekdes@desamandiri.test",
|
||||
"gender": "M"
|
||||
},
|
||||
{
|
||||
"id": "user_ketua_bumdes",
|
||||
"idUserRole": "admin",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_bumdes",
|
||||
"idPosition": "pos_ketua_bumdes",
|
||||
"nik": "3201010101010003",
|
||||
"name": "Ketua BUMDES",
|
||||
"phone": "081234567892",
|
||||
"email": "ketuabumdes@desamandiri.test",
|
||||
"gender": "M"
|
||||
},
|
||||
{
|
||||
"id": "user_ketua_karang_taruna",
|
||||
"idUserRole": "user",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_karang_taruna",
|
||||
"idPosition": "pos_ketua_karang_taruna",
|
||||
"nik": "3201010101010004",
|
||||
"name": "Ketua Karang Taruna",
|
||||
"phone": "081234567893",
|
||||
"email": "ketuakt@desamandiri.test",
|
||||
"gender": "M"
|
||||
},
|
||||
{
|
||||
"id": "user_warga1",
|
||||
"idUserRole": "user",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_rt01",
|
||||
"idPosition": "pos_staff_rt01",
|
||||
"nik": "3201010101010005",
|
||||
"name": "Warga Satu",
|
||||
"phone": "081234567894",
|
||||
"email": "wargasatu@desamandiri.test",
|
||||
"gender": "F"
|
||||
},
|
||||
{
|
||||
"id": "user_warga2",
|
||||
"idUserRole": "user",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_rt02",
|
||||
"idPosition": "pos_staff_rt02",
|
||||
"nik": "3201010101010006",
|
||||
"name": "Warga Dua",
|
||||
"phone": "081234567895",
|
||||
"email": "wargadua@desamandiri.test",
|
||||
"gender": "M"
|
||||
}
|
||||
];
|
||||
|
||||
// ANNOUNCEMENTS - Comprehensive dummy data
|
||||
const seederAnnouncementComprehensive = [
|
||||
{
|
||||
"id": "ann_pembangunan_jalan",
|
||||
"idVillage": "desaDummy",
|
||||
"title": "Pembangunan Jalan Desa Tahap 2",
|
||||
"desc": "Pada bulan ini akan dilakukan pembangunan jalan desa tahap 2 yang mencakup wilayah RT 01 dan RT 02. Mohon kerjasama warga untuk menyesuaikan aktivitas selama masa pembangunan.",
|
||||
"createdBy": "user_kades"
|
||||
},
|
||||
{
|
||||
"id": "ann_posyandu",
|
||||
"idVillage": "desaDummy",
|
||||
"title": "Posyandu Bulanan",
|
||||
"desc": "Posyandu bulan akan diselenggarakan pada tanggal 21 setiap bulannya di Balai Desa. Warga diharapkan aktif membawa balita untuk pemeriksaan kesehatan.",
|
||||
"createdBy": "user_sekdes"
|
||||
},
|
||||
{
|
||||
"id": "ann_rapat_warga",
|
||||
"idVillage": "desaDummy",
|
||||
"title": "Rapat Warga Bulanan",
|
||||
"desc": "Rapat warga bulanan akan diselenggarakan pada hari Sabtu, 25 Februari 2026 pukul 09.00 WIB di Balai Desa. Hadirilah tepat waktu.",
|
||||
"createdBy": "user_kades"
|
||||
}
|
||||
];
|
||||
|
||||
// ANNOUNCEMENT MEMBERS - Comprehensive dummy data
|
||||
const seederAnnouncementMemberComprehensive = [
|
||||
{
|
||||
"id": "ann_mem_pembangunan_jalan_rt01",
|
||||
"idAnnouncement": "ann_pembangunan_jalan",
|
||||
"idGroup": "group_rt01",
|
||||
"idDivision": null
|
||||
},
|
||||
{
|
||||
"id": "ann_mem_pembangunan_jalan_rt02",
|
||||
"idAnnouncement": "ann_pembangunan_jalan",
|
||||
"idGroup": "group_rt02",
|
||||
"idDivision": null
|
||||
},
|
||||
{
|
||||
"id": "ann_mem_posyandu_all",
|
||||
"idAnnouncement": "ann_posyandu",
|
||||
"idGroup": null,
|
||||
"idDivision": null
|
||||
},
|
||||
{
|
||||
"id": "ann_mem_rapat_warga_all",
|
||||
"idAnnouncement": "ann_rapat_warga",
|
||||
"idGroup": null,
|
||||
"idDivision": null
|
||||
}
|
||||
];
|
||||
|
||||
// DIVISIONS - Comprehensive dummy data
|
||||
const seederDivisionComprehensive = [
|
||||
{
|
||||
"id": "div_bumdes",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_bumdes",
|
||||
"name": "BUMDES Desa Mandiri",
|
||||
"desc": "Badan Usaha Milik Desa yang bertujuan untuk meningkatkan kesejahteraan masyarakat desa melalui berbagai usaha produktif.",
|
||||
"createdBy": "user_ketua_bumdes"
|
||||
},
|
||||
{
|
||||
"id": "div_karang_taruna",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_karang_taruna",
|
||||
"name": "Karang Taruna Desa Mandiri",
|
||||
"desc": "Organisasi pemuda desa yang berfokus pada pengembangan potensi pemuda dan kegiatan sosial kemasyarakatan.",
|
||||
"createdBy": "user_ketua_karang_taruna"
|
||||
},
|
||||
{
|
||||
"id": "div_linmas",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_rt01",
|
||||
"name": "Linmas Desa Mandiri",
|
||||
"desc": "Perlindungan Masyarakat yang bertugas menjaga ketertiban dan keamanan di wilayah desa.",
|
||||
"createdBy": "user_kades"
|
||||
}
|
||||
];
|
||||
|
||||
// DIVISION MEMBERS - Comprehensive dummy data
|
||||
const seederDivisionMemberComprehensive = [
|
||||
{
|
||||
"id": "div_mem_bumdes_ketua",
|
||||
"idDivision": "div_bumdes",
|
||||
"idUser": "user_ketua_bumdes",
|
||||
"isAdmin": true,
|
||||
"isLeader": true
|
||||
},
|
||||
{
|
||||
"id": "div_mem_bumdes_anggota1",
|
||||
"idDivision": "div_bumdes",
|
||||
"idUser": "user_warga1",
|
||||
"isAdmin": false,
|
||||
"isLeader": false
|
||||
},
|
||||
{
|
||||
"id": "div_mem_karang_taruna_ketua",
|
||||
"idDivision": "div_karang_taruna",
|
||||
"idUser": "user_ketua_karang_taruna",
|
||||
"isAdmin": true,
|
||||
"isLeader": true
|
||||
},
|
||||
{
|
||||
"id": "div_mem_karang_taruna_anggota1",
|
||||
"idDivision": "div_karang_taruna",
|
||||
"idUser": "user_warga2",
|
||||
"isAdmin": false,
|
||||
"isLeader": false
|
||||
},
|
||||
{
|
||||
"id": "div_mem_linmas_kades",
|
||||
"idDivision": "div_linmas",
|
||||
"idUser": "user_kades",
|
||||
"isAdmin": true,
|
||||
"isLeader": true
|
||||
}
|
||||
];
|
||||
|
||||
// PROJECTS - Comprehensive dummy data
|
||||
const seederProjectComprehensive = [
|
||||
{
|
||||
"id": "proj_pembangunan_jalan",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_rt01",
|
||||
"title": "Pembangunan Jalan Desa Tahap 2",
|
||||
"desc": "Pembangunan jalan desa tahap 2 yang mencakup wilayah RT 01 dan RT 02",
|
||||
"status": 1,
|
||||
"createdBy": "user_kades"
|
||||
},
|
||||
{
|
||||
"id": "proj_penghijauan",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_karang_taruna",
|
||||
"title": "Program Penghijauan Desa",
|
||||
"desc": "Penanaman pohon di sepanjang jalan desa dan area publik",
|
||||
"status": 0,
|
||||
"createdBy": "user_ketua_karang_taruna"
|
||||
},
|
||||
{
|
||||
"id": "proj_pembukuan_bumdes",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_bumdes",
|
||||
"title": "Sistem Pembukuan Digital BUMDES",
|
||||
"desc": "Pembuatan sistem pembukuan digital untuk BUMDES Desa Mandiri",
|
||||
"status": 0,
|
||||
"createdBy": "user_ketua_bumdes"
|
||||
}
|
||||
];
|
||||
|
||||
// PROJECT MEMBERS - Comprehensive dummy data
|
||||
const seederProjectMemberComprehensive = [
|
||||
{
|
||||
"id": "proj_mem_pembangunan_jalan_kades",
|
||||
"idProject": "proj_pembangunan_jalan",
|
||||
"idUser": "user_kades",
|
||||
"isLeader": true
|
||||
},
|
||||
{
|
||||
"id": "proj_mem_pembangunan_jalan_sekdes",
|
||||
"idProject": "proj_pembangunan_jalan",
|
||||
"idUser": "user_sekdes",
|
||||
"isLeader": false
|
||||
},
|
||||
{
|
||||
"id": "proj_mem_penghijauan_ketua_kt",
|
||||
"idProject": "proj_penghijauan",
|
||||
"idUser": "user_ketua_karang_taruna",
|
||||
"isLeader": true
|
||||
},
|
||||
{
|
||||
"id": "proj_mem_penghijauan_warga1",
|
||||
"idProject": "proj_penghijauan",
|
||||
"idUser": "user_warga1",
|
||||
"isLeader": false
|
||||
},
|
||||
{
|
||||
"id": "proj_mem_pembukuan_bumdes_ketua",
|
||||
"idProject": "proj_pembukuan_bumdes",
|
||||
"idUser": "user_ketua_bumdes",
|
||||
"isLeader": true
|
||||
}
|
||||
];
|
||||
|
||||
// PROJECT TASKS - Comprehensive dummy data
|
||||
const seederProjectTaskComprehensive = [
|
||||
{
|
||||
"id": "task_survey_lokasi",
|
||||
"idProject": "proj_pembangunan_jalan",
|
||||
"title": "Survey Lokasi",
|
||||
"desc": "Melakukan survey lokasi untuk menentukan titik pembangunan jalan",
|
||||
"status": 1,
|
||||
"dateStart": "2026-01-15T00:00:00.000Z",
|
||||
"dateEnd": "2026-01-20T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"id": "task_pengadaan_material",
|
||||
"idProject": "proj_pembangunan_jalan",
|
||||
"title": "Pengadaan Material",
|
||||
"desc": "Mengadakan material pembangunan seperti pasir, batu, dan semen",
|
||||
"status": 0,
|
||||
"dateStart": "2026-02-01T00:00:00.000Z",
|
||||
"dateEnd": "2026-02-10T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"id": "task_pelaksanaan_pembangunan",
|
||||
"idProject": "proj_pembangunan_jalan",
|
||||
"title": "Pelaksanaan Pembangunan",
|
||||
"desc": "Melaksanakan pembangunan jalan sesuai dengan desain yang telah ditentukan",
|
||||
"status": 0,
|
||||
"dateStart": "2026-02-15T00:00:00.000Z",
|
||||
"dateEnd": "2026-03-15T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"id": "task_penanaman_pohon",
|
||||
"idProject": "proj_penghijauan",
|
||||
"title": "Penanaman Pohon",
|
||||
"desc": "Menanam pohon di sepanjang jalan desa dan area publik",
|
||||
"status": 0,
|
||||
"dateStart": "2026-03-01T00:00:00.000Z",
|
||||
"dateEnd": "2026-03-15T00:00:00.000Z"
|
||||
}
|
||||
];
|
||||
|
||||
// DISCUSSIONS - Comprehensive dummy data
|
||||
const seederDiscussionComprehensive = [
|
||||
{
|
||||
"id": "disc_kegiatan_desa",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": null,
|
||||
"title": "Pembahasan Kegiatan Desa Mendatang",
|
||||
"desc": "Diskusi untuk merencanakan kegiatan desa yang akan datang dan menyerap aspirasi warga",
|
||||
"status": 1,
|
||||
"createdBy": "user_kades"
|
||||
},
|
||||
{
|
||||
"id": "disc_pengelolaan_sampah",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_rt01",
|
||||
"title": "Pengelolaan Sampah di RT 01",
|
||||
"desc": "Diskusi internal RT 01 mengenai pengelolaan sampah rumah tangga dan lingkungan",
|
||||
"status": 1,
|
||||
"createdBy": "user_kades"
|
||||
},
|
||||
{
|
||||
"id": "disc_program_karang_taruna",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_karang_taruna",
|
||||
"title": "Program Kerja Karang Taruna",
|
||||
"desc": "Merancang program kerja Karang Taruna untuk tahun ini",
|
||||
"status": 1,
|
||||
"createdBy": "user_ketua_karang_taruna"
|
||||
}
|
||||
];
|
||||
|
||||
// DISCUSSION MEMBERS - Comprehensive dummy data
|
||||
const seederDiscussionMemberComprehensive = [
|
||||
{
|
||||
"id": "disc_mem_kegiatan_desa_kades",
|
||||
"idDiscussion": "disc_kegiatan_desa",
|
||||
"idUser": "user_kades"
|
||||
},
|
||||
{
|
||||
"id": "disc_mem_kegiatan_desa_sekdes",
|
||||
"idDiscussion": "disc_kegiatan_desa",
|
||||
"idUser": "user_sekdes"
|
||||
},
|
||||
{
|
||||
"id": "disc_mem_kegiatan_desa_warga1",
|
||||
"idDiscussion": "disc_kegiatan_desa",
|
||||
"idUser": "user_warga1"
|
||||
},
|
||||
{
|
||||
"id": "disc_mem_pengelolaan_sampah_kades",
|
||||
"idDiscussion": "disc_pengelolaan_sampah",
|
||||
"idUser": "user_kades"
|
||||
},
|
||||
{
|
||||
"id": "disc_mem_pengelolaan_sampah_warga1",
|
||||
"idDiscussion": "disc_pengelolaan_sampah",
|
||||
"idUser": "user_warga1"
|
||||
},
|
||||
{
|
||||
"id": "disc_mem_program_kt_ketua",
|
||||
"idDiscussion": "disc_program_karang_taruna",
|
||||
"idUser": "user_ketua_karang_taruna"
|
||||
},
|
||||
{
|
||||
"id": "disc_mem_program_kt_warga2",
|
||||
"idDiscussion": "disc_program_karang_taruna",
|
||||
"idUser": "user_warga2"
|
||||
}
|
||||
];
|
||||
|
||||
try {
|
||||
// Start transaction to ensure data consistency
|
||||
await prisma.$transaction(async (tx) => {
|
||||
|
||||
// ADMIN ROLE
|
||||
for (let data of seederAdminRole) {
|
||||
await tx.adminRole.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
name: data.name
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// ADMIN
|
||||
for (let data of seederAdmin) {
|
||||
await tx.admin.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
name: data.name,
|
||||
idAdminRole: data.idAdminRole,
|
||||
phone: data.phone,
|
||||
email: data.email,
|
||||
gender: data.gender
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
idAdminRole: data.idAdminRole,
|
||||
phone: data.phone,
|
||||
email: data.email,
|
||||
gender: data.gender,
|
||||
name: data.name
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// THEME
|
||||
for (let data of seederTheme) {
|
||||
await tx.colorTheme.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
name: data.name,
|
||||
utama: data.utama,
|
||||
bgUtama: data.bgUtama,
|
||||
bgIcon: data.bgIcon,
|
||||
bgFiturHome: data.bgFiturHome,
|
||||
bgFiturDivision: data.bgFiturDivisi,
|
||||
bgTotalKegiatan: data.bgTotalKegiatan
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
utama: data.utama,
|
||||
bgUtama: data.bgUtama,
|
||||
bgIcon: data.bgIcon,
|
||||
bgFiturHome: data.bgFiturHome,
|
||||
bgFiturDivision: data.bgFiturDivisi,
|
||||
bgTotalKegiatan: data.bgTotalKegiatan
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// DESA - Original data
|
||||
for (let data of seederDesa) {
|
||||
await tx.village.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
name: data.name,
|
||||
desc: data.desc,
|
||||
idTheme: "theme1"
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
desc: data.desc,
|
||||
idTheme: "theme1"
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// GROUP - Original data
|
||||
for (let data of seederGroup) {
|
||||
await tx.group.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
name: data.name,
|
||||
idVillage: data.idVillage
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
idVillage: data.idVillage
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
for (let data of seederGroupComprehensive) {
|
||||
await tx.group.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
name: data.name,
|
||||
idVillage: data.idVillage
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
idVillage: data.idVillage
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// POSITION - Original data
|
||||
for (let data of seederPosition) {
|
||||
await tx.position.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
name: data.name,
|
||||
idGroup: data.idGroup
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
idGroup: data.idGroup
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
for (let data of seederPositionComprehensive) {
|
||||
await tx.position.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
name: data.name,
|
||||
idGroup: data.idGroup
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
idGroup: data.idGroup
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// USER ROLE
|
||||
for (let data of seederUserRole) {
|
||||
await tx.userRole.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
name: data.name
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
desc: data.desc
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// USER - Original data
|
||||
for (let data of seederUser) {
|
||||
await tx.user.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
idVillage: data.idVillage,
|
||||
idGroup: data.idGroup,
|
||||
idPosition: data.idPosition,
|
||||
idUserRole: data.idUserRole,
|
||||
nik: data.nik,
|
||||
name: data.name,
|
||||
phone: data.phone,
|
||||
email: data.email,
|
||||
gender: data.gender
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
idVillage: data.idVillage,
|
||||
idGroup: data.idGroup,
|
||||
idPosition: data.idPosition,
|
||||
idUserRole: data.idUserRole,
|
||||
nik: data.nik,
|
||||
name: data.name,
|
||||
phone: data.phone,
|
||||
email: data.email,
|
||||
gender: data.gender
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
for (let data of seederUserComprehensive) {
|
||||
await tx.user.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
idVillage: data.idVillage,
|
||||
idGroup: data.idGroup,
|
||||
idPosition: data.idPosition,
|
||||
idUserRole: data.idUserRole,
|
||||
nik: data.nik,
|
||||
name: data.name,
|
||||
phone: data.phone,
|
||||
email: data.email,
|
||||
gender: data.gender
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
idVillage: data.idVillage,
|
||||
idGroup: data.idGroup,
|
||||
idPosition: data.idPosition,
|
||||
idUserRole: data.idUserRole,
|
||||
nik: data.nik,
|
||||
name: data.name,
|
||||
phone: data.phone,
|
||||
email: data.email,
|
||||
gender: data.gender
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
for (let data of seederAnnouncementComprehensive) {
|
||||
await tx.announcement.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
title: data.title,
|
||||
desc: data.desc,
|
||||
createdBy: data.createdBy
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
idVillage: data.idVillage,
|
||||
title: data.title,
|
||||
desc: data.desc,
|
||||
createdBy: data.createdBy,
|
||||
isActive: true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
for (let data of seederAnnouncementMemberComprehensive) {
|
||||
await tx.announcementMember.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
idAnnouncement: data.idAnnouncement,
|
||||
idGroup: data.idGroup!,
|
||||
idDivision: data.idDivision!
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
idAnnouncement: data.idAnnouncement,
|
||||
idGroup: data.idGroup!,
|
||||
idDivision: data.idDivision!,
|
||||
isActive: true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
for (let data of seederDivisionComprehensive) {
|
||||
await tx.division.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
name: data.name,
|
||||
desc: data.desc,
|
||||
createdBy: data.createdBy
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
idVillage: data.idVillage,
|
||||
idGroup: data.idGroup,
|
||||
name: data.name,
|
||||
desc: data.desc,
|
||||
createdBy: data.createdBy,
|
||||
isActive: true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
for (let data of seederDivisionMemberComprehensive) {
|
||||
await tx.divisionMember.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
idUser: data.idUser,
|
||||
isAdmin: data.isAdmin,
|
||||
isLeader: data.isLeader
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
idDivision: data.idDivision,
|
||||
idUser: data.idUser,
|
||||
isAdmin: data.isAdmin,
|
||||
isLeader: data.isLeader,
|
||||
isActive: true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
for (let data of seederProjectComprehensive) {
|
||||
await tx.project.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
title: data.title,
|
||||
desc: data.desc,
|
||||
status: data.status,
|
||||
createdBy: data.createdBy
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
idVillage: data.idVillage,
|
||||
idGroup: data.idGroup,
|
||||
title: data.title,
|
||||
desc: data.desc,
|
||||
status: data.status,
|
||||
createdBy: data.createdBy,
|
||||
isActive: true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
for (let data of seederProjectMemberComprehensive) {
|
||||
await tx.projectMember.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
idUser: data.idUser,
|
||||
isLeader: data.isLeader
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
idProject: data.idProject,
|
||||
idUser: data.idUser,
|
||||
isLeader: data.isLeader,
|
||||
isActive: true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
for (let data of seederProjectTaskComprehensive) {
|
||||
await tx.projectTask.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
title: data.title,
|
||||
desc: data.desc,
|
||||
status: data.status,
|
||||
dateStart: new Date(data.dateStart),
|
||||
dateEnd: new Date(data.dateEnd)
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
idProject: data.idProject,
|
||||
title: data.title,
|
||||
desc: data.desc,
|
||||
status: data.status,
|
||||
dateStart: new Date(data.dateStart),
|
||||
dateEnd: new Date(data.dateEnd),
|
||||
isActive: true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
for (let data of seederDiscussionComprehensive) {
|
||||
await tx.discussion.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
title: data.title,
|
||||
desc: data.desc,
|
||||
status: data.status,
|
||||
createdBy: data.createdBy
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
idVillage: data.idVillage,
|
||||
idGroup: data.idGroup!,
|
||||
title: data.title,
|
||||
desc: data.desc,
|
||||
status: data.status,
|
||||
createdBy: data.createdBy,
|
||||
isActive: true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
for (let data of seederDiscussionMemberComprehensive) {
|
||||
await tx.discussionMember.upsert({
|
||||
where: {
|
||||
id: data.id
|
||||
},
|
||||
update: {
|
||||
idUser: data.idUser
|
||||
},
|
||||
create: {
|
||||
id: data.id,
|
||||
idDiscussion: data.idDiscussion,
|
||||
idUser: data.idUser,
|
||||
isActive: true
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
console.log("\n✅ Complete village data seeding completed successfully!");
|
||||
console.log(`📊 Total admin roles processed: ${seederAdminRole.length}`);
|
||||
console.log(`📊 Total admins processed: ${seederAdmin.length}`);
|
||||
console.log(`📊 Total themes processed: ${seederTheme.length}`);
|
||||
console.log(`📊 Total villages processed: ${seederDesa.length}`);
|
||||
console.log(`📊 Total groups processed: ${[...seederGroup, ...seederGroupComprehensive].length}`);
|
||||
console.log(`📊 Total positions processed: ${[...seederPosition, ...seederPositionComprehensive].length}`);
|
||||
console.log(`📊 Total user roles processed: ${seederUserRole.length}`);
|
||||
console.log(`📊 Total users processed: ${[...seederUser, ...seederUserComprehensive].length}`);
|
||||
console.log(`📊 Total announcements processed: ${seederAnnouncementComprehensive.length}`);
|
||||
console.log(`📊 Total announcement members processed: ${seederAnnouncementMemberComprehensive.length}`);
|
||||
console.log(`📊 Total divisions processed: ${seederDivisionComprehensive.length}`);
|
||||
console.log(`📊 Total division members processed: ${seederDivisionMemberComprehensive.length}`);
|
||||
console.log(`📊 Total projects processed: ${seederProjectComprehensive.length}`);
|
||||
console.log(`📊 Total project members processed: ${seederProjectMemberComprehensive.length}`);
|
||||
console.log(`📊 Total project tasks processed: ${seederProjectTaskComprehensive.length}`);
|
||||
console.log(`📊 Total discussions processed: ${seederDiscussionComprehensive.length}`);
|
||||
console.log(`📊 Total discussion members processed: ${seederDiscussionMemberComprehensive.length}`);
|
||||
} catch (error) {
|
||||
console.error("\n❌ Error during seeding:", error);
|
||||
throw new Error("Seeding process failed");
|
||||
} finally {
|
||||
await prisma.$disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
// Execute seeding if called directly from command line
|
||||
if (require.main === module) {
|
||||
seedCompleteVillageData()
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
export default seedCompleteVillageData;
|
||||
@@ -7,14 +7,6 @@
|
||||
"email": "amalia@bip.com",
|
||||
"gender": "F"
|
||||
},
|
||||
{
|
||||
"id": "devLukman",
|
||||
"idAdminRole": "dev",
|
||||
"name": "Lukman",
|
||||
"phone": "6287701790942",
|
||||
"email": "lukman@bip.com",
|
||||
"gender": "M"
|
||||
},
|
||||
{
|
||||
"id": "devLukman",
|
||||
"idAdminRole": "dev",
|
||||
|
||||
16
src/module/seeder/data/announcement.json
Normal file
16
src/module/seeder/data/announcement.json
Normal file
@@ -0,0 +1,16 @@
|
||||
[
|
||||
{
|
||||
"id": "ann_pembangunan_jalan",
|
||||
"idVillage": "desaDummy",
|
||||
"title": "Pembangunan Jalan Desa Tahap 2",
|
||||
"desc": "Pada bulan ini akan dilakukan pembangunan jalan desa tahap 2 yang mencakup wilayah RT 01 dan RT 02. Mohon kerjasama warga untuk menyesuaikan aktivitas selama masa pembangunan.",
|
||||
"createdBy": "user_kades"
|
||||
},
|
||||
{
|
||||
"id": "ann_rapat_warga",
|
||||
"idVillage": "desaDummy",
|
||||
"title": "Rapat Bulanan",
|
||||
"desc": "Rapat bulanan akan diselenggarakan pada hari Sabtu, 25 Februari 2026 pukul 09.00 WIB di Balai Desa. Hadirilah tepat waktu.",
|
||||
"createdBy": "user_kades"
|
||||
}
|
||||
]
|
||||
20
src/module/seeder/data/announcement_member.json
Normal file
20
src/module/seeder/data/announcement_member.json
Normal file
@@ -0,0 +1,20 @@
|
||||
[
|
||||
{
|
||||
"id": "ann_mem_pembangunan_jalan_rt01",
|
||||
"idAnnouncement": "ann_pembangunan_jalan",
|
||||
"idGroup": "group_rt01",
|
||||
"idDivision": "div_pelayanan"
|
||||
},
|
||||
{
|
||||
"id": "ann_mem_pembangunan_jalan_rt02",
|
||||
"idAnnouncement": "ann_pembangunan_jalan",
|
||||
"idGroup": "group_rt01",
|
||||
"idDivision": "div_umum"
|
||||
},
|
||||
{
|
||||
"id": "ann_mem_rapat_warga_all",
|
||||
"idAnnouncement": "ann_rapat_warga",
|
||||
"idGroup": "group_rt01",
|
||||
"idDivision": "div_umum"
|
||||
}
|
||||
]
|
||||
@@ -3,5 +3,10 @@
|
||||
"id": "desa1",
|
||||
"name": "Darmasaba",
|
||||
"desc": "-"
|
||||
},
|
||||
{
|
||||
"id": "desaDummy",
|
||||
"name": "Mandala",
|
||||
"desc": "Desa Dummy untuk testing"
|
||||
}
|
||||
]
|
||||
20
src/module/seeder/data/discussion.json
Normal file
20
src/module/seeder/data/discussion.json
Normal file
@@ -0,0 +1,20 @@
|
||||
[
|
||||
{
|
||||
"id": "disc_kegiatan_desa",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_rt01",
|
||||
"title": "Pembahasan Kegiatan Desa Mendatang",
|
||||
"desc": "Diskusi untuk merencanakan kegiatan desa yang akan datang dan menyerap aspirasi warga",
|
||||
"status": 1,
|
||||
"createdBy": "user_kades"
|
||||
},
|
||||
{
|
||||
"id": "disc_pengelolaan_sampah",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_rt01",
|
||||
"title": "Pengelolaan Sampah di RT 01",
|
||||
"desc": "Diskusi internal RT 01 mengenai pengelolaan sampah rumah tangga dan lingkungan",
|
||||
"status": 1,
|
||||
"createdBy": "user_kades"
|
||||
}
|
||||
]
|
||||
27
src/module/seeder/data/discussion_member.json
Normal file
27
src/module/seeder/data/discussion_member.json
Normal file
@@ -0,0 +1,27 @@
|
||||
[
|
||||
{
|
||||
"id": "disc_mem_kegiatan_desa_kades",
|
||||
"idDiscussion": "disc_kegiatan_desa",
|
||||
"idUser": "user_sekdes"
|
||||
},
|
||||
{
|
||||
"id": "disc_mem_kegiatan_desa_sekdes",
|
||||
"idDiscussion": "disc_kegiatan_desa",
|
||||
"idUser": "user_warga1"
|
||||
},
|
||||
{
|
||||
"id": "disc_mem_kegiatan_desa_warga1",
|
||||
"idDiscussion": "disc_kegiatan_desa",
|
||||
"idUser": "user_warga2"
|
||||
},
|
||||
{
|
||||
"id": "disc_mem_pengelolaan_sampah_kades",
|
||||
"idDiscussion": "disc_pengelolaan_sampah",
|
||||
"idUser": "user_warga1"
|
||||
},
|
||||
{
|
||||
"id": "disc_mem_pengelolaan_sampah_warga1",
|
||||
"idDiscussion": "disc_pengelolaan_sampah",
|
||||
"idUser": "user_warga2"
|
||||
}
|
||||
]
|
||||
18
src/module/seeder/data/division.json
Normal file
18
src/module/seeder/data/division.json
Normal file
@@ -0,0 +1,18 @@
|
||||
[
|
||||
{
|
||||
"id": "div_pelayanan",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_rt01",
|
||||
"name": "Seksi Pelayanan",
|
||||
"desc": "Bertanggung jawab atas pelayanan administrasi umum, perizinan, dan kebutuhan dokumen masyarakat desa.",
|
||||
"createdBy": "user_kades"
|
||||
},
|
||||
{
|
||||
"id": "div_umum",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_rt01",
|
||||
"name": "Urusan Tata Usaha dan Umum",
|
||||
"desc": "Menangani administrasi perkantoran, arsip desa, inventaris aset, dan operasional kantor desa.",
|
||||
"createdBy": "user_kades"
|
||||
}
|
||||
]
|
||||
30
src/module/seeder/data/division_member.json
Normal file
30
src/module/seeder/data/division_member.json
Normal file
@@ -0,0 +1,30 @@
|
||||
[
|
||||
{
|
||||
"id": "div_mem_linmas_warga1",
|
||||
"idDivision": "div_pelayanan",
|
||||
"idUser": "user_warga1",
|
||||
"isAdmin": false,
|
||||
"isLeader": false
|
||||
},
|
||||
{
|
||||
"id": "div_mem_linmas_warga2",
|
||||
"idDivision": "div_pelayanan",
|
||||
"idUser": "user_warga2",
|
||||
"isAdmin": false,
|
||||
"isLeader": false
|
||||
},
|
||||
{
|
||||
"id": "div_mem_umum_warga3",
|
||||
"idDivision": "div_umum",
|
||||
"idUser": "user_warga3",
|
||||
"isAdmin": false,
|
||||
"isLeader": false
|
||||
},
|
||||
{
|
||||
"id": "div_mem_umum_warga4",
|
||||
"idDivision": "div_umum",
|
||||
"idUser": "user_warga4",
|
||||
"isAdmin": false,
|
||||
"isLeader": false
|
||||
}
|
||||
]
|
||||
@@ -3,5 +3,25 @@
|
||||
"id": "group1",
|
||||
"idVillage": "desa1",
|
||||
"name": "Dinas"
|
||||
},
|
||||
{
|
||||
"id": "group_rt01",
|
||||
"idVillage": "desaDummy",
|
||||
"name": "Dinas"
|
||||
},
|
||||
{
|
||||
"id": "group_rt02",
|
||||
"idVillage": "desaDummy",
|
||||
"name": "Adat"
|
||||
},
|
||||
{
|
||||
"id": "group_karang_taruna",
|
||||
"idVillage": "desaDummy",
|
||||
"name": "Karang Taruna"
|
||||
},
|
||||
{
|
||||
"id": "group_bumdes",
|
||||
"idVillage": "desaDummy",
|
||||
"name": "PKK"
|
||||
}
|
||||
]
|
||||
@@ -3,5 +3,25 @@
|
||||
"id": "position1",
|
||||
"idGroup": "group1",
|
||||
"name": "Perbekel"
|
||||
},
|
||||
{
|
||||
"id": "pos_ketua_rt01",
|
||||
"idGroup": "group_rt01",
|
||||
"name": "Perbekel"
|
||||
},
|
||||
{
|
||||
"id": "pos_sekretaris_rt01",
|
||||
"idGroup": "group_rt01",
|
||||
"name": "Sekretaris"
|
||||
},
|
||||
{
|
||||
"id": "pos_bendahara_rt01",
|
||||
"idGroup": "group_rt01",
|
||||
"name": "Bendahara"
|
||||
},
|
||||
{
|
||||
"id": "pos_staff_rt01",
|
||||
"idGroup": "group_rt01",
|
||||
"name": "Staff"
|
||||
}
|
||||
]
|
||||
11
src/module/seeder/data/project.json
Normal file
11
src/module/seeder/data/project.json
Normal file
@@ -0,0 +1,11 @@
|
||||
[
|
||||
{
|
||||
"id": "proj_pembangunan_jalan",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_rt01",
|
||||
"title": "Pembangunan Jalan Desa Tahap 2",
|
||||
"desc": "Pembangunan jalan desa tahap 2 yang mencakup wilayah RT 01 dan RT 02",
|
||||
"status": 1,
|
||||
"createdBy": "user_kades"
|
||||
}
|
||||
]
|
||||
14
src/module/seeder/data/project_member.json
Normal file
14
src/module/seeder/data/project_member.json
Normal file
@@ -0,0 +1,14 @@
|
||||
[
|
||||
{
|
||||
"id": "proj_mem_pembangunan_jalan_kades",
|
||||
"idProject": "proj_pembangunan_jalan",
|
||||
"idUser": "user_warga1",
|
||||
"isLeader": true
|
||||
},
|
||||
{
|
||||
"id": "proj_mem_pembangunan_jalan_sekdes",
|
||||
"idProject": "proj_pembangunan_jalan",
|
||||
"idUser": "user_warga2",
|
||||
"isLeader": false
|
||||
}
|
||||
]
|
||||
29
src/module/seeder/data/project_task.json
Normal file
29
src/module/seeder/data/project_task.json
Normal file
@@ -0,0 +1,29 @@
|
||||
[
|
||||
{
|
||||
"id": "task_survey_lokasi",
|
||||
"idProject": "proj_pembangunan_jalan",
|
||||
"title": "Survey Lokasi",
|
||||
"desc": "Melakukan survey lokasi untuk menentukan titik pembangunan jalan",
|
||||
"status": 1,
|
||||
"dateStart": "2026-01-15T00:00:00.000Z",
|
||||
"dateEnd": "2026-01-20T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"id": "task_pengadaan_material",
|
||||
"idProject": "proj_pembangunan_jalan",
|
||||
"title": "Pengadaan Material",
|
||||
"desc": "Mengadakan material pembangunan seperti pasir, batu, dan semen",
|
||||
"status": 0,
|
||||
"dateStart": "2026-02-01T00:00:00.000Z",
|
||||
"dateEnd": "2026-02-10T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"id": "task_pelaksanaan_pembangunan",
|
||||
"idProject": "proj_pembangunan_jalan",
|
||||
"title": "Pelaksanaan Pembangunan",
|
||||
"desc": "Melaksanakan pembangunan jalan sesuai dengan desain yang telah ditentukan",
|
||||
"status": 0,
|
||||
"dateStart": "2026-02-15T00:00:00.000Z",
|
||||
"dateEnd": "2026-03-15T00:00:00.000Z"
|
||||
}
|
||||
]
|
||||
@@ -10,5 +10,77 @@
|
||||
"phone": "628980185458",
|
||||
"email": "amalia_dev@bip.com",
|
||||
"gender": "F"
|
||||
},
|
||||
{
|
||||
"id": "user_kades",
|
||||
"idUserRole": "supadmin",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_rt01",
|
||||
"idPosition": "pos_ketua_rt01",
|
||||
"nik": "3201010101010001",
|
||||
"name": "Juli Ningrum",
|
||||
"phone": "081234567890",
|
||||
"email": "juli@gmail.com",
|
||||
"gender": "F"
|
||||
},
|
||||
{
|
||||
"id": "user_sekdes",
|
||||
"idUserRole": "admin",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_rt01",
|
||||
"idPosition": "pos_sekretaris_rt01",
|
||||
"nik": "3201010101010002",
|
||||
"name": "Salwa Kusmawati",
|
||||
"phone": "081234567891",
|
||||
"email": "salwa@gmail.com",
|
||||
"gender": "F"
|
||||
},
|
||||
{
|
||||
"id": "user_warga1",
|
||||
"idUserRole": "user",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_rt01",
|
||||
"idPosition": "pos_staff_rt01",
|
||||
"nik": "3201010101010005",
|
||||
"name": "Bakidin Wibowo",
|
||||
"phone": "6",
|
||||
"email": "bakidin@gmail.com",
|
||||
"gender": "M"
|
||||
},
|
||||
{
|
||||
"id": "user_warga2",
|
||||
"idUserRole": "user",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_rt01",
|
||||
"idPosition": "pos_staff_rt01",
|
||||
"nik": "3201010101010006",
|
||||
"name": "Jais Kurniawan",
|
||||
"phone": "081234567895",
|
||||
"email": "jais@gmail.com",
|
||||
"gender": "M"
|
||||
},
|
||||
{
|
||||
"id": "user_warga3",
|
||||
"idUserRole": "user",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_rt01",
|
||||
"idPosition": "pos_staff_rt01",
|
||||
"nik": "3201010101010007",
|
||||
"name": "Safira Oktaviani S.I.Kom",
|
||||
"phone": "081234567896",
|
||||
"email": "safira@gmail.com",
|
||||
"gender": "F"
|
||||
},
|
||||
{
|
||||
"id": "user_warga4",
|
||||
"idUserRole": "user",
|
||||
"idVillage": "desaDummy",
|
||||
"idGroup": "group_rt01",
|
||||
"idPosition": "pos_staff_rt01",
|
||||
"nik": "3201010101010008",
|
||||
"name": "Agus Setiawan",
|
||||
"phone": "081234567897",
|
||||
"email": "agus@gmail.com",
|
||||
"gender": "M"
|
||||
}
|
||||
]
|
||||
@@ -1,10 +1,20 @@
|
||||
import seederAdminRole from "./data/admin_role.json";
|
||||
import seederAdmin from "./data/admin.json";
|
||||
import seederUserRole from "./data/user_role.json";
|
||||
import seederUser from "./data/user.json";
|
||||
import seederAdminRole from "./data/admin_role.json";
|
||||
import seederAnnouncement from "./data/announcement.json";
|
||||
import seederAnnouncementMember from "./data/announcement_member.json";
|
||||
import seederDesa from "./data/desa.json";
|
||||
import seederDiscussion from "./data/discussion.json";
|
||||
import seederDiscussionMember from "./data/discussion_member.json";
|
||||
import seederDivision from "./data/division.json";
|
||||
import seederDivisionMember from "./data/division_member.json";
|
||||
import seederGroup from "./data/group.json";
|
||||
import seederPosition from "./data/position.json";
|
||||
import seederProject from "./data/project.json";
|
||||
import seederProjectMember from "./data/project_member.json";
|
||||
import seederProjectTask from "./data/project_task.json";
|
||||
import seederTheme from "./data/theme.json";
|
||||
import seederUser from "./data/user.json";
|
||||
import seederUserRole from "./data/user_role.json";
|
||||
|
||||
export { seederAdmin, seederAdminRole, seederAnnouncement, seederAnnouncementMember, seederDesa, seederDiscussion, seederDiscussionMember, seederDivision, seederDivisionMember, seederGroup, seederPosition, seederProject, seederProjectMember, seederProjectTask, seederTheme, seederUser, seederUserRole };
|
||||
|
||||
export { seederAdminRole, seederAdmin, seederDesa, seederGroup, seederPosition, seederUserRole, seederUser, seederTheme }
|
||||
Reference in New Issue
Block a user