feat: Trip-specific bag selection with duration-based Carry-On vs Checked Bag auto-matching
This commit is contained in:
1 parent
be586ea386
commit
2d709cfd9b
5 files changed
+506
-70
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { BagType, PackingItem, LuggageConfig, CustomBag } from '../types';
|
||||
import { sound } from '../utils/audio';
|
||||
import {
|
||||
@@ -11,7 +11,9 @@ import {
|
||||
Settings2,
|
||||
Camera,
|
||||
Compass,
|
||||
Tag
|
||||
Tag,
|
||||
Check,
|
||||
Luggage
|
||||
} from 'lucide-react';
|
||||
|
||||
interface BagOverviewProps {
|
||||
@@ -19,7 +21,9 @@ interface BagOverviewProps {
|
||||
selectedBag: BagType | 'all';
|
||||
onSelectBag: (bag: BagType | 'all') => void;
|
||||
luggageConfig: LuggageConfig;
|
||||
activeTripBags: CustomBag[];
|
||||
customBags: CustomBag[];
|
||||
onToggleTripBag: (bagId: BagType) => void;
|
||||
onEditBags: () => void;
|
||||
}
|
||||
|
||||
@@ -46,35 +50,48 @@ export const BagOverview: React.FC<BagOverviewProps> = ({
|
||||
items,
|
||||
selectedBag,
|
||||
onSelectBag,
|
||||
luggageConfig,
|
||||
activeTripBags,
|
||||
customBags,
|
||||
onToggleTripBag,
|
||||
onEditBags,
|
||||
}) => {
|
||||
// Filter bags based on luggage mode if it's a default bag
|
||||
const visibleBags = customBags.filter((b) => {
|
||||
if (b.id === 'carry_on' && luggageConfig === 'backpack_only') return false;
|
||||
if (b.id === 'checked' && luggageConfig !== 'checked_bag') return false;
|
||||
return true;
|
||||
});
|
||||
const [showTripBagPicker, setShowTripBagPicker] = useState(false);
|
||||
const visibleBags = activeTripBags;
|
||||
|
||||
return (
|
||||
<div className="mb-6">
|
||||
<div className="flex items-center justify-between mb-2 flex-wrap gap-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex items-center gap-1.5 sm:gap-2 flex-wrap">
|
||||
<span className="font-mono text-xs uppercase font-bold text-ink tracking-wider">
|
||||
LUGGAGE ALLOCATION // "WHAT GOES IN WHAT BAG"
|
||||
TRIP BAGS ({visibleBags.length}/{customBags.length})
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
sound.playClick();
|
||||
setShowTripBagPicker(!showTripBagPicker);
|
||||
}}
|
||||
className={`font-mono text-[11px] font-bold px-2 py-0.5 border border-ink transition-colors flex items-center gap-1 shadow-xs ${
|
||||
showTripBagPicker
|
||||
? 'bg-ink text-canary'
|
||||
: 'bg-canary/80 hover:bg-canary text-ink'
|
||||
}`}
|
||||
title="Select which bags are going on this specific trip"
|
||||
>
|
||||
<Luggage size={12} />
|
||||
<span>SELECT TRIP BAGS</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
sound.playClick();
|
||||
onEditBags();
|
||||
}}
|
||||
className="font-mono text-[11px] font-bold px-2 py-0.5 border border-ink bg-white hover:bg-canary text-ink transition-colors flex items-center gap-1 shadow-xs"
|
||||
title="Add, rename, or reconfigure bags"
|
||||
className="font-mono text-[11px] font-bold px-2 py-0.5 border border-ink bg-white hover:bg-ticket-200 text-ink transition-colors flex items-center gap-1 shadow-xs"
|
||||
title="Add, rename, or reconfigure your global bag pool"
|
||||
>
|
||||
<Settings2 size={12} />
|
||||
<span>EDIT BAGS</span>
|
||||
<span>EDIT BAG POOL</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -91,10 +108,53 @@ export const BagOverview: React.FC<BagOverviewProps> = ({
|
||||
}`}
|
||||
>
|
||||
<Layers size={13} />
|
||||
<span>VIEW ALL BAGS ({items.length})</span>
|
||||
<span>VIEW ALL ({items.length})</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Inline Trip Bag Loadout Switcher */}
|
||||
{showTripBagPicker && (
|
||||
<div className="mb-3 p-3 bg-ticket-100 border-2 border-ink shadow-card-hard-sm animate-in fade-in duration-100">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<span className="font-mono text-[11px] font-bold uppercase text-ink">
|
||||
WHICH BAGS ARE GOING ON THIS TRIP? (UNCHECKED BAGS AUTOMATICALLY MOVE ITEMS TO YOUR MAIN BAG)
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{customBags.map((bag) => {
|
||||
const isBringing = visibleBags.some((b) => b.id === bag.id);
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
key={bag.id}
|
||||
onClick={() => {
|
||||
sound.playClick();
|
||||
onToggleTripBag(bag.id);
|
||||
}}
|
||||
className={`px-2.5 py-1.5 border-2 font-mono text-xs font-bold flex items-center gap-2 transition-all ${
|
||||
isBringing
|
||||
? 'bg-canary-light border-ink text-ink shadow-card-hard-sm'
|
||||
: 'bg-white/60 border-ink/40 text-ink/50 hover:bg-white hover:text-ink'
|
||||
}`}
|
||||
>
|
||||
<span
|
||||
className={`w-4 h-4 border border-ink flex items-center justify-center ${
|
||||
isBringing ? 'bg-ink text-canary' : 'bg-white'
|
||||
}`}
|
||||
>
|
||||
{isBringing && <Check size={11} strokeWidth={3} />}
|
||||
</span>
|
||||
<span>{bag.label}</span>
|
||||
<span className="text-[10px] bg-ink text-ticket-100 px-1 py-0.2">
|
||||
{bag.tagCode}
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="grid grid-cols-2 lg:grid-cols-4 gap-2 sm:gap-3">
|
||||
{visibleBags.map((b) => {
|
||||
const bagItems = items.filter((i) => i.bag === b.id);
|
||||
|
||||
Reference in new issue
Block a user