Files
travelplanning/MAKE_NOTE.md
T

5.3 KiB

Markdown

To AI Agent: Implement Automatic Tour Note Generation & Dynamic Timeline Quick Note Insertion

1. Context & Feature Overview

We are implementing an interconnected Note System for the Yotrip Travel Planner application. The feature spans across three core components: TourDetailPage.tsx, MyNotePage.tsx, and ItineraryTimeline.tsx.

Core Requirements:

  1. Auto-Note Initialization: When a new Tour is created in TourDetailPage.tsx, the system must automatically instantiate a matching master note record inside the MyNotePage.tsx system linked by tourId.
  2. Strict Document Schema Hierarchy: The note content must format itself using structured headings reflecting the tour's legs (stages) and location points.
  3. Timeline Quick Note Insertion: Inside ItineraryTimeline.tsx, each location node must feature a "Quick Note Button". Clicking it must immediately stringify location metadata (Timestamp + Reverse-Geocoded Address + User Text) and INSERT it dynamically under the correct Stage section inside the master note.

2. Note Structure & Markdown Payload Template

When initializing a tour or syncing content, the document data payload within the database/state framework must stringify exactly to this structural template:

# [Tên Tour]

## Ghi chú chung
*(Nội dung ghi chú tổng quan của chuyến đi...)*

## Ghi chú: [Tên Chặng 1]
#### 📅 [Ngày giờ] | 📍 [Tên địa điểm - Phân giải từ tọa độ]
- **Nhật ký:** [Nội dung người dùng nhập vào ở Điểm này trên Timeline]

## Ghi chú: [Tên Chặng 2]
#### ...

## 3. Detailed Logic & Component Specifications
### Step 1: TourDetailPage.tsx - Creation Hook Handler
When the user submits the "Create Tour" form successfully, inject an asynchronous action handler to create the accompanying node container:

TypeScript
// Blueprint for Tour Creation Action Hook
const handleCreateTour = async (tourData: any) => {
  const newTour = await api.tours.create(tourData);
  
  if (newTour) {
    // Generate the initial markdown note layout template
    const initialNoteBody = `# ${newTour.title}\n\n## Ghi chú chung\n\n`;
    
    await api.notes.create({
      tourId: newTour.id,
      title: `Ghi chú: ${newTour.title}`,
      content: initialNoteBody,
      createdAt: new Date().toISOString()
    });
  }
};

### Step 2: ItineraryTimeline.tsx - Quick Note Component Injection
Locate the location list renderer (leg.locations.map) adjacent to the white circular checkpoint nodes. Insert a small "Quick Note" button (utilizing Lucide icon FileText or similar).

JSX Target Insertion Blueprint
JavaScript

{/* Quick Note Button Interface sitting right near the action buttons of the card */}
<button 
  onClick={() => handleQuickNoteInsert(leg.id, location.id, location)}
  className="p-1.5 text-yotripLight-steel hover:text-yotripLight-text dark:text-yotripDark-muted dark:hover:text-yotripDark-lime rounded-lg hover:bg-gray-100 dark:hover:bg-yotripDark-surface-muted transition-colors"
  title="Ghi chú nhanh điểm này"
>
  <FileText className="w-4 h-4" />
</button>

### Step 3: Coordinate Resolution & String Insertion Engine
Implement the core method to reverse-geocode latitudes/longitudes, construct the standard string layout, and push the patch to the existing text repository of the note.

TypeScript

const handleQuickNoteInsert = async (legId: string, locationId: string, locationData: any) => {
  // 1. Resolve coordinates to a readable address string
  const resolvedAddress = await reverseGeocode(locationData.lat, locationData.lng) || locationData.addressName;
  
  // 2. Format localized Date/Time
  const formattedTime = locationData.plannedStart 
    ? new Date(locationData.plannedStart).toLocaleString('vi-VN') 
    : "Thời gian tùy hứng";
  
  // 3. Extract user text inputted on the timeline card
  const userInputText = locationData.timelineComment || "Không có ghi chú thêm.";
  
  // 4. Synthesize the injection block
  const noteSnippet = `#### 📅 ${formattedTime} | 📍 ${resolvedAddress}\n- **Nhật ký:** ${userInputText}\n\n`;
  
  // 5. Trigger API/State update to find the master note by tourId,
  // locate or append the '## Ghi chú: [Tên Chặng]' marker, and inject the snippet directly below it.
  await api.notes.insertSectionByTourId(tourId, legId, noteSnippet);
};

## 4. UI Style Integration Constraints
Apply the application design system colors directly to the new buttons.

In Light mode, buttons must remain a clean #28536b (Yale Blue) or soft #7ea8be (Steel Blue).

In Dark mode, hover interactions must transition to #bce784 (Lime Cream) with a smooth transition-colors duration-200 modifier.

## 5. Acceptance Criteria for Verification
[ ] Instantiation Check: Create a test Tour titled "Hoa vàng cỏ xanh 2026". Navigate to MyNotePage and confirm a note document with the exact title has been instantly spawned.

[ ] Geocoding & String Format Check: Click the Quick Note button on a location card with coordinates (e.g., 15.56, 108.49). The string appended to the note must fully resolve the address (e.g., "Tam Kỳ, Quảng Nam") instead of dumping raw coordinate numbers.

[ ] Structural Targeting: Ensure that inserting a quick note from Chặng 2 appends the text directly beneath the ## Ghi chú: Chặng 2 markdown anchor block, without scrambling or overwriting the text blocks of Chặng 1.