fix: Submenu active state + currency symbols + flags integration
1. Fixed Submenu Active State ✅ Problem: First submenu always active due to pathname.startsWith() - /dashboard matches /dashboard/analytics - Both items show as active Solution: Use exact match instead - const isActive = pathname === it.path - Only clicked item shows as active Files: DashboardSubmenuBar.tsx, SubmenuBar.tsx 2. Fixed Currency Symbol Display ✅ Problem: HTML entities showing (ءإ) Solution: Use currency code when symbol has HTML entities Before: United Arab Emirates dirham (ءإ) After: United Arab Emirates dirham (AED) Logic: const displaySymbol = (!currency.symbol || currency.symbol.includes('&#')) ? currency.code : currency.symbol; 3. Integrated Flags.json ✅ A. Moved flags.json to admin-spa/src/data/ B. Added flag support to SearchableSelect component - New icon prop in Option interface - Displays flag before label in trigger - Displays flag before label in dropdown C. Currency select now shows flags - Flag icon next to each currency - Visual country identification - Better UX for currency selection D. Dynamic store summary with flag Before: 🇮🇩 Your store is located in Indonesia After: [FLAG] Your store is located in Indonesia - Flag based on selected currency - Country name from flags.json - Currency name (not just code) - Dynamic updates when currency changes Benefits: ✅ Clear submenu navigation ✅ Readable currency symbols ✅ Visual country flags ✅ Better currency selection UX ✅ Dynamic store location display Files Modified: - DashboardSubmenuBar.tsx: Exact match for active state - SubmenuBar.tsx: Exact match for active state - Store.tsx: Currency symbol fix + flags integration - searchable-select.tsx: Icon support - flags.json: Moved to admin-spa/src/data/
This commit is contained in:
@@ -22,6 +22,8 @@ export interface Option {
|
||||
label: React.ReactNode;
|
||||
/** Optional text used for filtering. Falls back to string label or value. */
|
||||
searchText?: string;
|
||||
/** Optional icon (base64 image or URL) to display before the label */
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
@@ -65,7 +67,12 @@ export function SearchableSelect({
|
||||
aria-disabled={disabled}
|
||||
tabIndex={disabled ? -1 : 0}
|
||||
>
|
||||
{selected ? selected.label : placeholder}
|
||||
<div className="flex items-center gap-2 flex-1 min-w-0">
|
||||
{selected?.icon && (
|
||||
<img src={selected.icon} alt="" className="w-5 h-4 object-cover rounded-sm flex-shrink-0" />
|
||||
)}
|
||||
<span className="truncate">{selected ? selected.label : placeholder}</span>
|
||||
</div>
|
||||
<ChevronsUpDown className="opacity-50 h-4 w-4 shrink-0" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
@@ -99,12 +106,15 @@ export function SearchableSelect({
|
||||
{showCheckIndicator && (
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
"mr-2 h-4 w-4 flex-shrink-0",
|
||||
opt.value === value ? "opacity-100" : "opacity-0"
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{opt.label}
|
||||
{opt.icon && (
|
||||
<img src={opt.icon} alt="" className="w-5 h-4 object-cover rounded-sm mr-2 flex-shrink-0" />
|
||||
)}
|
||||
<span className="truncate">{opt.label}</span>
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandList>
|
||||
|
||||
Reference in New Issue
Block a user