7.0 KiB
7.0 KiB
name, description
| name | description |
|---|---|
| feature-guide | 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
- User membuka aplikasi → landing di halaman Home
- Bisa search destinasi atau browse dari grid card
- Filter berdasarkan kategori dan budget
- Klik card → modal konfirmasi trip (isi tanggal, nama trip)
- Confirm → redirect ke
/schedule
Data yang Diperlukan
// 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
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 effectTripSelector.jsx— modal form input tanggal & nama tripSearchBar.jsx— search dengan debounceFilterBar.jsx— filter kategori (pills/tabs)
Fitur 2: Daily Schedule Builder (Schedule Page)
File: src/pages/Schedule.jsx
Alur User
- User masuk ke
/schedule - Melihat tab per hari (Day 1, Day 2, ...)
- Klik "+ Tambah Aktivitas" → modal form
- Aktivitas ditampilkan di timeline vertikal
- Bisa drag & drop untuk reorder
Komponen yang Dibutuhkan
DayTabs.jsx— tab navigasi per hariScheduleTimeline.jsx— timeline visualActivityItem.jsx— satu item aktivitas (draggable)AddActivityModal.jsx— form tambah/edit aktivitas
Implementasi Drag & Drop
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
// 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
- User masuk ke
/packing - Melihat daftar per kategori dengan progress
- Centang item yang sudah dipak
- Tambah item baru di kategori tertentu
- Load template sesuai tipe trip
Template Packing
// 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 keseluruhanPackingCategory.jsx— section per kategori dengan sub-listPackingItem.jsx— checkbox item + qty counter + delete
Logic Progress
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
- User masuk ke
/budget - Set total budget di bagian atas
- Tambah pengeluaran satu per satu
- Melihat ringkasan dan chart
- Warning merah jika over budget
Komponen yang Dibutuhkan
BudgetHeader.jsx— input total budget + overview card (total, spent, remaining)BudgetChart.jsx— Recharts PieChart + BarChartExpenseList.jsx— list semua pengeluaranAddExpenseModal.jsx— form tambah pengeluaran
Recharts Integration
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
// 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)