mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-19 13:21:46 +00:00
fix(tests): restore packing panel inline header + update tests for ui changes
- PackingListPanel accepts inlineHeader prop (default true) to keep its
legacy title and inline import button; ListsContainer passes
inlineHeader={false} since the toolbar now owns those controls
- ReservationModal tests look for the renamed 'Car' button (was 'Rental Car')
- Budget total-budget test asserts against the split integer/decimal
spans that replaced the single text node
This commit is contained in:
@@ -416,8 +416,8 @@ describe('BudgetPanel', () => {
|
|||||||
render(<BudgetPanel tripId={1} />);
|
render(<BudgetPanel tripId={1} />);
|
||||||
await screen.findByText('Flight');
|
await screen.findByText('Flight');
|
||||||
await screen.findByText('Hotel');
|
await screen.findByText('Hotel');
|
||||||
// Grand total card shows 300.00
|
// Grand total card shows 300.00 (integer and decimal are rendered in separate spans)
|
||||||
expect(screen.getByText('300.00')).toBeInTheDocument();
|
expect(document.body.textContent?.replace(/\s+/g, '')).toMatch(/300[,.]00/);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('FE-COMP-BUDGET-033: read-only mode hides add/delete/edit controls', async () => {
|
it('FE-COMP-BUDGET-033: read-only mode hides add/delete/edit controls', async () => {
|
||||||
|
|||||||
@@ -730,9 +730,10 @@ interface PackingListPanelProps {
|
|||||||
tripId: number
|
tripId: number
|
||||||
items: PackingItem[]
|
items: PackingItem[]
|
||||||
openImportSignal?: number
|
openImportSignal?: number
|
||||||
|
inlineHeader?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function PackingListPanel({ tripId, items, openImportSignal = 0 }: PackingListPanelProps) {
|
export default function PackingListPanel({ tripId, items, openImportSignal = 0, inlineHeader = true }: PackingListPanelProps) {
|
||||||
const [filter, setFilter] = useState('alle') // 'alle' | 'offen' | 'erledigt'
|
const [filter, setFilter] = useState('alle') // 'alle' | 'offen' | 'erledigt'
|
||||||
const [addingCategory, setAddingCategory] = useState(false)
|
const [addingCategory, setAddingCategory] = useState(false)
|
||||||
const [newCatName, setNewCatName] = useState('')
|
const [newCatName, setNewCatName] = useState('')
|
||||||
@@ -1008,14 +1009,34 @@ export default function PackingListPanel({ tripId, items, openImportSignal = 0 }
|
|||||||
<div style={{ display: 'flex', flexDirection: 'column', height: '100%', ...font }}>
|
<div style={{ display: 'flex', flexDirection: 'column', height: '100%', ...font }}>
|
||||||
|
|
||||||
{/* ── Header ── */}
|
{/* ── Header ── */}
|
||||||
<div style={{ padding: '0 0 16px', flexShrink: 0 }}>
|
<div style={{ padding: inlineHeader ? '20px 24px 16px' : '0 0 16px', flexShrink: 0, borderBottom: inlineHeader ? '1px solid rgba(0,0,0,0.06)' : undefined }}>
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 14 }}>
|
<div style={{ display: 'flex', alignItems: inlineHeader ? 'flex-start' : 'center', justifyContent: 'space-between', gap: 14 }}>
|
||||||
{items.length > 0 ? (
|
{inlineHeader ? (
|
||||||
<p style={{ margin: 0, fontSize: 12.5, color: 'var(--text-faint)' }}>
|
<div>
|
||||||
{t('packing.progress', { packed: abgehakt, total: items.length, percent: fortschritt })}
|
<h2 style={{ margin: 0, fontSize: 18, fontWeight: 700, color: 'var(--text-primary)' }}>{t('packing.title')}</h2>
|
||||||
</p>
|
{items.length > 0 && (
|
||||||
) : <span />}
|
<p style={{ margin: '2px 0 0', fontSize: 12.5, color: 'var(--text-faint)' }}>
|
||||||
|
{t('packing.progress', { packed: abgehakt, total: items.length, percent: fortschritt })}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
items.length > 0 ? (
|
||||||
|
<p style={{ margin: 0, fontSize: 12.5, color: 'var(--text-faint)' }}>
|
||||||
|
{t('packing.progress', { packed: abgehakt, total: items.length, percent: fortschritt })}
|
||||||
|
</p>
|
||||||
|
) : <span />
|
||||||
|
)}
|
||||||
<div style={{ display: 'flex', gap: 6 }}>
|
<div style={{ display: 'flex', gap: 6 }}>
|
||||||
|
{inlineHeader && canEdit && (
|
||||||
|
<button onClick={() => setShowImportModal(true)} style={{
|
||||||
|
display: 'flex', alignItems: 'center', gap: 5, padding: '5px 11px', borderRadius: 99,
|
||||||
|
border: '1px solid var(--border-primary)', fontSize: 12, fontWeight: 500, cursor: 'pointer',
|
||||||
|
fontFamily: 'inherit', background: 'var(--bg-card)', color: 'var(--text-muted)',
|
||||||
|
}}>
|
||||||
|
<Upload size={12} /> <span className="hidden sm:inline">{t('packing.import')}</span>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
{canEdit && abgehakt > 0 && (
|
{canEdit && abgehakt > 0 && (
|
||||||
<button onClick={handleClearChecked} style={{
|
<button onClick={handleClearChecked} style={{
|
||||||
fontSize: 11.5, padding: '5px 10px', borderRadius: 99, border: '1px solid rgba(239,68,68,0.3)',
|
fontSize: 11.5, padding: '5px 10px', borderRadius: 99, border: '1px solid rgba(239,68,68,0.3)',
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ describe('ReservationModal', () => {
|
|||||||
expect(screen.getByRole('button', { name: /Accommodation/i })).toBeInTheDocument();
|
expect(screen.getByRole('button', { name: /Accommodation/i })).toBeInTheDocument();
|
||||||
expect(screen.getByRole('button', { name: /Restaurant/i })).toBeInTheDocument();
|
expect(screen.getByRole('button', { name: /Restaurant/i })).toBeInTheDocument();
|
||||||
expect(screen.getByRole('button', { name: /Train/i })).toBeInTheDocument();
|
expect(screen.getByRole('button', { name: /Train/i })).toBeInTheDocument();
|
||||||
expect(screen.getByRole('button', { name: /Rental Car/i })).toBeInTheDocument();
|
expect(screen.getByRole('button', { name: /^Car$/i })).toBeInTheDocument();
|
||||||
expect(screen.getByRole('button', { name: /Cruise/i })).toBeInTheDocument();
|
expect(screen.getByRole('button', { name: /Cruise/i })).toBeInTheDocument();
|
||||||
expect(screen.getByRole('button', { name: /Event/i })).toBeInTheDocument();
|
expect(screen.getByRole('button', { name: /Event/i })).toBeInTheDocument();
|
||||||
expect(screen.getByRole('button', { name: /Tour/i })).toBeInTheDocument();
|
expect(screen.getByRole('button', { name: /Tour/i })).toBeInTheDocument();
|
||||||
@@ -636,7 +636,7 @@ describe('ReservationModal', () => {
|
|||||||
|
|
||||||
it('FE-PLANNER-RESMODAL-045: car type shows date/time section', async () => {
|
it('FE-PLANNER-RESMODAL-045: car type shows date/time section', async () => {
|
||||||
render(<ReservationModal {...defaultProps} />);
|
render(<ReservationModal {...defaultProps} />);
|
||||||
await userEvent.click(screen.getByRole('button', { name: /Rental Car/i }));
|
await userEvent.click(screen.getByRole('button', { name: /^Car$/i }));
|
||||||
// Car type still shows date fields (not hotel which hides them)
|
// Car type still shows date fields (not hotel which hides them)
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(screen.getAllByTestId('date-picker').length).toBeGreaterThan(0);
|
expect(screen.getAllByTestId('date-picker').length).toBeGreaterThan(0);
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ function ListsContainer({ tripId, packingItems, todoItems }: { tripId: number; p
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ padding: '16px 28px 0' }} className="max-md:!px-4">
|
<div style={{ padding: '16px 28px 0' }} className="max-md:!px-4">
|
||||||
{subTab === 'packing' && <PackingListPanel tripId={tripId} items={packingItems} openImportSignal={importPackingSignal} />}
|
{subTab === 'packing' && <PackingListPanel tripId={tripId} items={packingItems} openImportSignal={importPackingSignal} inlineHeader={false} />}
|
||||||
{subTab === 'todo' && <TodoListPanel tripId={tripId} items={todoItems} addItemSignal={addTodoSignal} />}
|
{subTab === 'todo' && <TodoListPanel tripId={tripId} items={todoItems} addItemSignal={addTodoSignal} />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user