Files
TREK/client/src/components/Assistant/AssistantRemembered.tsx
T
Maurice d1b8cb20a3 feat(assistant): found places open the place form, notes kept on its own, city walk stops checked off
- Found places: the strip shows only when the answer names one of them, the
  named ones first. A click on a card, or "Add to trip", opens the planner's
  place form filled in with the place on the day in focus, its Google details
  (photos, hours, description) loading beside it; "+ Day" and the day grid
  are gone.
- Trip notes: remember_for_trip runs at once without a card. The assistant
  keeps lasting facts the user mentions (who travels, needs, likes, budget,
  pace) on its own and offers the unsure ones as a follow-up; the chat shows
  "Noted for this trip: ..." with the notes a tap away, and reads them again
  so the dialog never saves over the new note.
- City walks: set_city_walk_visit checks a station off on its day (visited,
  skipped, or the mark taken back), with day_edit as in the day plan, a
  change card naming the station and its walk, and an undo that restores the
  status before while the station is as the change left it.
- Card heads are a step smaller (32px tile, smaller title and count), and the
  dot beside "Working on it" in the header is gone.
2026-10-23 18:21:54 +02:00

50 lines
2.1 KiB
TypeScript

import { BookmarkCheck, Pencil } from 'lucide-react';
import { useEffect, useState } from 'react';
import { useTranslation } from '../../i18n';
import { useSettingsStore } from '../../store/settingsStore';
import { Tooltip } from '../shared/Tooltip';
import AssistantMemoryDialog from './AssistantMemoryDialog';
import { useAssistantScope } from './assistantViewContext';
/**
* A note the assistant kept in the trip notes on its own, as a quiet line in
* its answer, with the notes a tap away to change or drop it. Kept while the
* answer is written, the notes on this device are read again, so the dialog
* never saves over the note with what it held before.
*/
export default function AssistantRemembered({ note, live }: { note: string; live: boolean }) {
const { t } = useTranslation();
const scope = useAssistantScope();
const loadSettings = useSettingsStore((s) => s.loadSettings);
const [editing, setEditing] = useState(false);
useEffect(() => {
if (live) void loadSettings();
}, [live, loadSettings]);
const tripId = scope.kind === 'trip' ? scope.tripId : null;
return (
<div className="flex min-w-0 items-center gap-2 rounded-lg bg-surface-secondary px-2.5 py-1.5 text-caption">
<BookmarkCheck size={13} strokeWidth={2.2} aria-hidden="true" className="flex-none text-success" />
<span className="min-w-0 flex-1">
<span className="font-semibold text-content-secondary">{t('assistant.memory.kept')}</span>{' '}
<bdi className="text-content-muted">{note}</bdi>
</span>
{tripId !== null && (
<Tooltip label={t('assistant.memory.edit')} placement="top">
<button
type="button"
onClick={() => setEditing(true)}
aria-label={t('assistant.memory.edit')}
className="grid h-6 w-6 flex-none place-items-center rounded-md text-content-faint transition-colors hover:bg-surface-hover hover:text-content"
>
<Pencil size={12} aria-hidden="true" />
</button>
</Tooltip>
)}
{editing && tripId !== null && <AssistantMemoryDialog tripId={tripId} onClose={() => setEditing(false)} />}
</div>
);
}