auto winn
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
---
|
||||
name: feature-guide
|
||||
description: Panduan implementasi masing-masing fitur utama Tour Planner App (Trip Selection, Schedule Builder, Packing List, Budget Calculator). Gunakan skill ini saat memulai atau melanjutkan pengerjaan satu halaman/fitur tertentu.
|
||||
---
|
||||
|
||||
# Skill: Feature Guide — Tour Planner App
|
||||
|
||||
## Fitur 1: Trip Selection (Home Page)
|
||||
|
||||
**File:** `src/pages/Home.jsx`
|
||||
|
||||
### Alur User
|
||||
1. User membuka aplikasi → landing di halaman Home
|
||||
2. Bisa search destinasi atau browse dari grid card
|
||||
3. Filter berdasarkan kategori dan budget
|
||||
4. Klik card → modal konfirmasi trip (isi tanggal, nama trip)
|
||||
5. Confirm → redirect ke `/schedule`
|
||||
|
||||
### Data yang Diperlukan
|
||||
```javascript
|
||||
// src/data/destinations.js
|
||||
export const destinations = [
|
||||
{
|
||||
id: 'bali-001',
|
||||
name: 'Bali',
|
||||
country: 'Indonesia',
|
||||
category: 'pantai', // 'pantai' | 'gunung' | 'kota' | 'budaya'
|
||||
description: 'Surga tropis...',
|
||||
highlights: ['Tanah Lot', 'Ubud', 'Kuta Beach'],
|
||||
estimatedBudget: { min: 2000000, max: 5000000 },
|
||||
popularDuration: 4, // hari
|
||||
rating: 4.8,
|
||||
reviewCount: 12400,
|
||||
image: '/assets/bali.jpg', // atau URL picsum
|
||||
tags: ['romantis', 'budaya', 'alam'],
|
||||
bestTime: 'April - Oktober',
|
||||
},
|
||||
// minimal 10 destinasi
|
||||
];
|
||||
```
|
||||
|
||||
### State yang Diupdate
|
||||
```javascript
|
||||
setTrip({
|
||||
id: destination.id,
|
||||
name: tripName, // input user
|
||||
destination: destination.name,
|
||||
startDate: startDate, // dari date picker
|
||||
endDate: endDate,
|
||||
totalDays: diffInDays(startDate, endDate) + 1,
|
||||
coverImage: destination.image,
|
||||
type: 'preset',
|
||||
category: destination.category,
|
||||
});
|
||||
initSchedule(totalDays, startDate); // inisialisasi array schedule
|
||||
```
|
||||
|
||||
### Komponen yang Dibutuhkan
|
||||
- `TripCard.jsx` — card destinasi dengan image, info, hover effect
|
||||
- `TripSelector.jsx` — modal form input tanggal & nama trip
|
||||
- `SearchBar.jsx` — search dengan debounce
|
||||
- `FilterBar.jsx` — filter kategori (pills/tabs)
|
||||
|
||||
---
|
||||
|
||||
## Fitur 2: Daily Schedule Builder (Schedule Page)
|
||||
|
||||
**File:** `src/pages/Schedule.jsx`
|
||||
|
||||
### Alur User
|
||||
1. User masuk ke `/schedule`
|
||||
2. Melihat tab per hari (Day 1, Day 2, ...)
|
||||
3. Klik "+ Tambah Aktivitas" → modal form
|
||||
4. Aktivitas ditampilkan di timeline vertikal
|
||||
5. Bisa drag & drop untuk reorder
|
||||
|
||||
### Komponen yang Dibutuhkan
|
||||
- `DayTabs.jsx` — tab navigasi per hari
|
||||
- `ScheduleTimeline.jsx` — timeline visual
|
||||
- `ActivityItem.jsx` — satu item aktivitas (draggable)
|
||||
- `AddActivityModal.jsx` — form tambah/edit aktivitas
|
||||
|
||||
### Implementasi Drag & Drop
|
||||
```jsx
|
||||
import { DndContext, closestCenter, KeyboardSensor, PointerSensor, useSensor, useSensors } from '@dnd-kit/core';
|
||||
import { SortableContext, verticalListSortingStrategy, arrayMove } from '@dnd-kit/sortable';
|
||||
import { useSortable } from '@dnd-kit/sortable';
|
||||
import { CSS } from '@dnd-kit/utilities';
|
||||
|
||||
// Di ActivityItem — tambahkan useSortable
|
||||
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: activity.id });
|
||||
const style = { transform: CSS.Transform.toString(transform), transition };
|
||||
|
||||
// Di ScheduleTimeline — wrap dengan DndContext
|
||||
<DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
|
||||
<SortableContext items={activityIds} strategy={verticalListSortingStrategy}>
|
||||
{activities.map(a => <ActivityItem key={a.id} activity={a} />)}
|
||||
</SortableContext>
|
||||
</DndContext>
|
||||
```
|
||||
|
||||
### Template Aktivitas Cepat
|
||||
```javascript
|
||||
// src/data/activities.js
|
||||
export const activityTemplates = [
|
||||
{ name: 'Sarapan', category: 'makan', duration: 60, defaultTime: '07:00' },
|
||||
{ name: 'Check-in Hotel', category: 'check-in', duration: 30, defaultTime: '14:00' },
|
||||
{ name: 'Makan Siang', category: 'makan', duration: 60, defaultTime: '12:00' },
|
||||
{ name: 'Makan Malam', category: 'makan', duration: 90, defaultTime: '18:30' },
|
||||
{ name: 'Kunjungan Wisata', category: 'wisata', duration: 120, defaultTime: '10:00' },
|
||||
{ name: 'Belanja Oleh-oleh', category: 'lainnya', duration: 60, defaultTime: '16:00' },
|
||||
{ name: 'Berangkat/Transportasi', category: 'transportasi', duration: 180, defaultTime: '06:00' },
|
||||
];
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Fitur 3: Packing List Manager (PackingList Page)
|
||||
|
||||
**File:** `src/pages/PackingList.jsx`
|
||||
|
||||
### Alur User
|
||||
1. User masuk ke `/packing`
|
||||
2. Melihat daftar per kategori dengan progress
|
||||
3. Centang item yang sudah dipak
|
||||
4. Tambah item baru di kategori tertentu
|
||||
5. Load template sesuai tipe trip
|
||||
|
||||
### Template Packing
|
||||
```javascript
|
||||
// src/data/packingTemplates.js
|
||||
export const packingTemplates = {
|
||||
pantai: {
|
||||
Pakaian: [
|
||||
{ name: 'Baju pantai', qty: 3 },
|
||||
{ name: 'Celana pendek', qty: 2 },
|
||||
{ name: 'Kacamata hitam', qty: 1 },
|
||||
],
|
||||
// ...
|
||||
},
|
||||
gunung: { /* ... */ },
|
||||
kota: { /* ... */ },
|
||||
budaya: { /* ... */ },
|
||||
};
|
||||
```
|
||||
|
||||
### Komponen yang Dibutuhkan
|
||||
- `PackingOverview.jsx` — statistik total item & progress keseluruhan
|
||||
- `PackingCategory.jsx` — section per kategori dengan sub-list
|
||||
- `PackingItem.jsx` — checkbox item + qty counter + delete
|
||||
|
||||
### Logic Progress
|
||||
```javascript
|
||||
const getTotalStats = (packingList) => {
|
||||
let total = 0, checked = 0;
|
||||
Object.values(packingList).forEach(items => {
|
||||
items.forEach(item => {
|
||||
total++;
|
||||
if (item.checked) checked++;
|
||||
});
|
||||
});
|
||||
return { total, checked, percent: total > 0 ? Math.round((checked/total)*100) : 0 };
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Fitur 4: Budget Calculator (Budget Page)
|
||||
|
||||
**File:** `src/pages/Budget.jsx`
|
||||
|
||||
### Alur User
|
||||
1. User masuk ke `/budget`
|
||||
2. Set total budget di bagian atas
|
||||
3. Tambah pengeluaran satu per satu
|
||||
4. Melihat ringkasan dan chart
|
||||
5. Warning merah jika over budget
|
||||
|
||||
### Komponen yang Dibutuhkan
|
||||
- `BudgetHeader.jsx` — input total budget + overview card (total, spent, remaining)
|
||||
- `BudgetChart.jsx` — Recharts PieChart + BarChart
|
||||
- `ExpenseList.jsx` — list semua pengeluaran
|
||||
- `AddExpenseModal.jsx` — form tambah pengeluaran
|
||||
|
||||
### Recharts Integration
|
||||
```jsx
|
||||
import { PieChart, Pie, Cell, Tooltip, ResponsiveContainer, BarChart, Bar, XAxis, YAxis } from 'recharts';
|
||||
|
||||
// Data untuk pie chart
|
||||
const pieData = Object.entries(byCategory).map(([name, value]) => ({ name, value }));
|
||||
|
||||
<ResponsiveContainer width="100%" height={240}>
|
||||
<PieChart>
|
||||
<Pie data={pieData} cx="50%" cy="50%" outerRadius={80} dataKey="value">
|
||||
{pieData.map((entry, index) => (
|
||||
<Cell key={index} fill={BUDGET_CATEGORY_COLORS[entry.name]} />
|
||||
))}
|
||||
</Pie>
|
||||
<Tooltip formatter={(value) => formatIDR(value)} />
|
||||
</PieChart>
|
||||
</ResponsiveContainer>
|
||||
```
|
||||
|
||||
### Format Currency
|
||||
```javascript
|
||||
// src/utils/formatCurrency.js
|
||||
export const formatIDR = (amount) =>
|
||||
new Intl.NumberFormat('id-ID', { style: 'currency', currency: 'IDR', minimumFractionDigits: 0 }).format(amount);
|
||||
|
||||
export const formatUSD = (amount) =>
|
||||
new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(amount);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Navigasi Antar Halaman
|
||||
|
||||
```
|
||||
/ (Home) → pilih trip
|
||||
/schedule → jadwal harian
|
||||
/packing → packing list
|
||||
/budget → kalkulasi budget
|
||||
```
|
||||
|
||||
Navbar harus selalu tampil dan menampilkan:
|
||||
- Logo / nama app
|
||||
- Link ke semua 4 halaman
|
||||
- Indikator halaman aktif
|
||||
- Badge progress (% packing done, budget status)
|
||||
Reference in New Issue
Block a user