- Krisna Guntur Pamungkas (241080200051)
- Rafli Achmad Nalisga (241080200028)
- Raden Mochammad R. F. (241080200066)
Lost & Found adalah sistem informasi berbasis web yang dirancang untuk membantu civitas akademika dalam melaporkan dan menemukan barang hilang di lingkungan kampus.
Sistem ini memungkinkan mahasiswa untuk:
- Melaporkan barang yang hilang agar diketahui oleh civitas lain
- Melaporkan barang yang ditemukan agar dapat dikembalikan ke pemiliknya
- Menelusuri galeri laporan secara real-time
- Mengelola riwayat laporan pribadi melalui halaman profil
lost-found/
├── frontend/ # React + Vite
├── backend/ # Node.js + Express
└── database/ # Supabase/PostgreSQL
Proyek menggunakan arsitektur client-server terpisah (decoupled):
| Layer | Teknologi | Deskripsi |
|---|---|---|
| Frontend | React 19, Vite 8, React Router v7 | SPA dengan routing berbasis halaman |
| Backend | Node.js, Express.js | REST API dengan autentikasi JWT |
| Database | PostgreSQL via Supabase | Penyimpanan data pengguna & laporan |
| Storage | Supabase Storage | Upload foto barang |
| Nodemailer + Gmail SMTP | Pengiriman OTP verifikasi |
- Registrasi akun dengan verifikasi email via kode OTP
- Login menggunakan email atau NIM + password
- Forgot Password dengan verifikasi kombinasi email & NIM
- Reset Password menggunakan token JWT sementara
- Semua password di-hash menggunakan bcrypt
- Proteksi endpoint dengan JWT Bearer Token
- Laporan Kehilangan — Form melaporkan barang yang hilang beserta lokasi, tanggal, dan kontak
- Laporan Penemuan — Form melaporkan barang yang ditemukan agar bisa diklaim pemiliknya
- Upload Foto — Mendukung format JPG, JPEG, PNG, GIF, WEBP (maks. 5 MB) via Supabase Storage
- Filter Galeri — Filter laporan berdasarkan tipe (lost/found) dan status (available/claimed)
- Klaim Barang — Pemilik laporan dapat menandai barang sebagai sudah diklaim (claimed)
- Halaman profil menampilkan riwayat laporan pribadi
- Data dipisahkan antara laporan kehilangan dan penemuan
- Dokumentasi interaktif dengan Swagger UI (OpenAPI 3.0)
- Tersedia di endpoint
/api-docs
lost-found/
│
├── backend/
│ ├── src/
│ │ ├── app.js # Entry point Express
│ │ ├── config/
│ │ │ ├── supabase.js # Supabase client
│ │ │ ├── mail.js # Nodemailer config (OTP)
│ │ │ └── swagger.js # OpenAPI 3.0 spec
│ │ ├── controllers/
│ │ │ ├── authController.js # Register, Login, OTP, Reset Password
│ │ │ └── itemController.js # CRUD laporan barang
│ │ ├── middleware/
│ │ │ └── auth.js # JWT authentication middleware
│ │ ├── routes/
│ │ │ ├── auth.js # Route /api/auth/*
│ │ │ └── items.js # Route /api/items/*
│ │ └── utils/
│ │ ├── jwt.js # Generate & verify JWT
│ │ └── otp.js # Generate kode OTP
│ └── package.json
│
├── frontend/
│ ├── src/
│ │ ├── App.jsx # Routing utama
│ │ ├── api/
│ │ │ └── axios.js # Axios instance + interceptor
│ │ ├── context/
│ │ │ └── AuthContext.jsx # Global auth state (React Context)
│ │ ├── components/
│ │ │ ├── Header.jsx # Navbar
│ │ │ ├── Sidebar.jsx # Sidebar navigasi
│ │ │ ├── Layout.jsx # Wrapper layout halaman utama
│ │ │ ├── ProtectedRoute.jsx # Guard route terproteksi
│ │ │ └── ItemModal.jsx # Modal detail item
│ │ └── pages/
│ │ ├── Login.jsx # Halaman login
│ │ ├── Register.jsx # Halaman registrasi
│ │ ├── OtpVerification.jsx# Verifikasi kode OTP
│ │ ├── ForgotPassword.jsx # Lupa password
│ │ ├── ResetPassword.jsx # Reset password baru
│ │ ├── Home.jsx # Dashboard / halaman utama
│ │ ├── Gallery.jsx # Galeri barang ditemukan
│ │ ├── LostItems.jsx # Daftar barang hilang
│ │ ├── FormSelection.jsx # Pilih tipe laporan
│ │ ├── FormFound.jsx # Form laporan penemuan
│ │ ├── FormLost.jsx # Form laporan kehilangan
│ │ └── Profile.jsx # Profil & riwayat laporan
│ └── package.json
│
└── database/
└── migration.sql # Skema tabel PostgreSQL
| Kolom | Tipe | Keterangan |
|---|---|---|
id |
BIGSERIAL PK | ID unik pengguna |
name |
VARCHAR(100) | Nama lengkap |
email |
VARCHAR(100) UNIQUE | Email kampus |
nim |
VARCHAR(50) UNIQUE | Nomor Induk Mahasiswa |
password |
VARCHAR(255) | Password (bcrypt hash) |
role |
VARCHAR(50) | Default: Mahasiswa |
profile_image |
VARCHAR(255) | URL foto profil |
otp_code |
VARCHAR(6) | Kode OTP aktif |
otp_expiry |
TIMESTAMPTZ | Batas waktu OTP (15 menit) |
is_verified |
BOOLEAN | Status verifikasi email |
created_at |
TIMESTAMPTZ | Waktu registrasi |
| Kolom | Tipe | Keterangan |
|---|---|---|
id |
BIGSERIAL PK | ID unik laporan |
user_id |
BIGINT FK | Referensi ke tabel users |
item_name |
VARCHAR(100) | Nama barang |
description |
TEXT | Deskripsi detail |
location |
VARCHAR(100) | Lokasi kejadian |
found_date |
DATE | Tanggal hilang/ditemukan |
contact_phone |
VARCHAR(20) | Nomor kontak pelapor |
image |
TEXT | URL foto barang (Supabase Storage) |
type |
VARCHAR(10) | lost atau found |
status |
VARCHAR(20) | available atau claimed |
created_at |
TIMESTAMPTZ | Waktu laporan dibuat |
- Node.js v18 atau lebih baru
- npm v9 atau lebih baru
- Akun Supabase (database & storage)
- Akun Gmail dengan App Password (untuk SMTP OTP)
git clone <url-repository>
cd lost-foundcd backend
npm installBuat file .env berdasarkan .env.example:
# Server
PORT=5000
# JWT
JWT_SECRET=
JWT_EXPIRES_IN=7d
# Supabase
SUPABASE_URL=https://your-project-id.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your_service_role_key_here
# SMTP (Gmail)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your_email@gmail.com
SMTP_PASS=your_app_password_here
SMTP_FROM_NAME=Lost & FoundJalankan migrasi database di Supabase SQL Editor menggunakan file database/migration.sql.
Jalankan server backend:
npm run dev # Development (nodemon)
npm start # ProductionServer berjalan di http://localhost:5000
cd frontend
npm installBuat file .env:
VITE_API_URL=http://localhost:5000Jalankan development server:
npm run devAplikasi berjalan di http://localhost:5173
Dokumentasi API interaktif tersedia setelah backend berjalan:
| URL | Keterangan |
|---|---|
http://localhost:5000/api-docs |
Swagger UI — dokumentasi interaktif |
http://localhost:5000/api-docs.json |
OpenAPI 3.0 JSON spec |
| Method | Endpoint | Auth | Deskripsi |
|---|---|---|---|
| POST | /register |
❌ | Registrasi akun baru |
| POST | /login |
❌ | Login, mendapatkan JWT token |
| POST | /verify-otp |
❌ | Verifikasi kode OTP |
| POST | /forgot-password |
❌ | Request OTP reset password |
| POST | /reset-password |
✅ | Reset password baru |
| GET | /me |
✅ | Data profil user aktif |
| Method | Endpoint | Auth | Deskripsi |
|---|---|---|---|
| GET | / |
✅ | Daftar laporan (filter: type, status) |
| GET | /my |
✅ | Laporan milik user yang login |
| POST | / |
✅ | Buat laporan baru (multipart/form-data) |
| PATCH | /:id/status |
✅ | Update status laporan |
Catatan: Endpoint bertanda ✅ memerlukan header
Authorization: Bearer <token>
- Password di-hash menggunakan bcrypt (salt rounds: 10)
- Autentikasi berbasis JWT (expire: 7 hari)
- OTP bersifat one-time dan kadaluarsa dalam 15 menit
- Upload file divalidasi tipe ekstensi dan dibatasi maksimal 5 MB
- Row Level Security (RLS) diaktifkan di Supabase
| Teknologi | Versi | Fungsi |
|---|---|---|
| React | 19 | UI framework |
| Vite | 8 | Build tool & dev server |
| React Router DOM | 7 | Client-side routing |
| Axios | 1.18 | HTTP client ke backend |
| Teknologi | Versi | Fungsi |
|---|---|---|
| Node.js | ≥18 | Runtime JavaScript |
| Express.js | 4 | Web framework |
| bcryptjs | 2.4 | Hash password |
| jsonwebtoken | 9 | JWT auth |
| Multer | 1.4 | Upload file handler |
| Nodemailer | 6.9 | Kirim email OTP |
| swagger-jsdoc | — | Generate OpenAPI spec |
| swagger-ui-express | — | Serve Swagger UI |
| Layanan | Fungsi |
|---|---|
| Supabase (PostgreSQL) | Database relasional |
| Supabase Storage | Penyimpanan foto barang |
| Gmail SMTP | Pengiriman email OTP |