Files
Ready-to-Planner-Tour/.agents/rules/coding-standards.md
T
2026-08-27 19:45:15 +07:00

187 lines
4.4 KiB
Markdown

# Coding Standards — Tour Planner App
Aturan ini berlaku untuk semua kode yang ditulis dalam proyek ini.
AI agent wajib mengikuti seluruh aturan di bawah ini.
---
## 1. Struktur Komponen
```jsx
// ✅ BENAR — Functional component dengan arrow function
const MyComponent = ({ prop1, prop2 }) => {
// hooks di atas
// logic di tengah
// return di bawah
return <div />;
};
export default MyComponent;
// ❌ SALAH — Jangan gunakan class component
class MyComponent extends React.Component { }
```
---
## 2. Styling
```jsx
// ✅ BENAR — CSS variables dari design system
<div style={{ color: 'var(--color-text-primary)', padding: 'var(--space-4)' }}>
// ✅ BENAR — className dengan class yang didefinisikan di CSS
<div className="glass section-title">
// ❌ SALAH — Hardcode warna
<div style={{ color: '#ffffff', backgroundColor: '#1a1a2e' }}>
// ❌ SALAH — TailwindCSS
<div className="text-white bg-gray-900 p-4">
```
---
## 3. State Management
```javascript
// ✅ BENAR — Gunakan Zustand store untuk state yang di-share
const { schedule, addActivity } = useTourStore();
// ✅ BENAR — useState untuk state lokal (form, toggle)
const [isOpen, setIsOpen] = useState(false);
// ❌ SALAH — Prop drilling lebih dari 2 level
<A> <B prop={x}> <C prop={x}> <D prop={x} />
```
---
## 4. Animasi
```jsx
// ✅ BENAR — Selalu gunakan Framer Motion
import { motion } from 'framer-motion';
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }}>
// ❌ SALAH — Animasi manual
setTimeout(() => setVisible(true), 100);
element.style.transition = 'opacity 0.3s';
```
---
## 5. Icons
```jsx
// ✅ BENAR — Lucide React
import { MapPin, Calendar, Plane } from 'lucide-react';
<MapPin size={20} />
// ❌ SALAH — Emoji sebagai icon UI
<span>📍</span>
// ❌ SALAH — SVG inline tanpa abstraksi
<svg xmlns="..." viewBox="..."><path d="..." /></svg>
```
---
## 6. Data & Constants
```javascript
// ✅ BENAR — Data di src/data/
import { destinations } from '../data/destinations';
import { CATEGORY_COLORS } from '../data/constants';
// ❌ SALAH — Data hardcode di dalam komponen
const destinations = [{ name: 'Bali', ... }]; // dalam file .jsx
```
---
## 7. File Naming
| Tipe | Convention | Contoh |
|------|------------|--------|
| Component | PascalCase | `TripCard.jsx` |
| Hook | camelCase dengan "use" prefix | `useBudget.js` |
| Utility | camelCase | `formatCurrency.js` |
| Data file | camelCase | `destinations.js` |
| CSS | kebab-case | `trip-card.css` |
---
## 8. Import Order
```javascript
// 1. React & hooks
import { useState, useEffect } from 'react';
// 2. Third-party libraries
import { motion, AnimatePresence } from 'framer-motion';
import { MapPin } from 'lucide-react';
// 3. Internal store & hooks
import { useTourStore } from '../store/tourStore';
import { useBudget } from '../hooks/useBudget';
// 4. Components
import Button from '../components/ui/Button';
import TripCard from '../components/trip/TripCard';
// 5. Data & utils
import { destinations } from '../data/destinations';
import { formatIDR } from '../utils/formatCurrency';
// 6. Styles (jika ada)
import './ComponentName.css';
```
---
## 9. Performance
- Gunakan `useMemo` untuk kalkulasi berat (total budget, statistik packing)
- Gunakan `useCallback` untuk handler yang di-pass sebagai prop
- Gunakan `React.memo` untuk komponen list item yang berat
- Jangan lakukan side effect tanpa `useEffect`
---
## 10. Batasan Fitur (TIDAK BOLEH DILANGGAR)
| Larangan | Alasan |
|----------|--------|
| ❌ Login / Logout | Aplikasi ini sepenuhnya static & lokal |
| ❌ API call ke backend | Tidak ada server, semua data lokal |
| ❌ Menyimpan password atau data sensitif | Tidak ada autentikasi |
| ❌ TailwindCSS | Gunakan vanilla CSS + CSS variables |
| ❌ jQuery atau manipulasi DOM manual | Gunakan React state |
| ❌ `console.log` di production code | Hapus sebelum commit |
---
## 11. Aksesibilitas (Minimum Requirements)
- Semua tombol punya `aria-label` jika tidak ada teks
- Semua form field punya `<label>` yang terhubung
- Warna kontras minimum 4.5:1 untuk teks
- Keyboard navigable untuk modal (focus trap)
---
## 12. Error Handling
```javascript
// Selalu handle edge case
const totalDays = trip?.totalDays ?? 0;
const activities = schedule[dayIndex]?.activities ?? [];
// Jangan biarkan crash karena undefined
// ❌
const name = trip.name.toUpperCase(); // crash jika trip.name null
// ✅
const name = trip?.name?.toUpperCase() ?? 'Unnamed Trip';
```