- SellerDashboard: migrado para Shell (header topo), removida sidebar lateral, cards KPI brancos com react-icons pretos (FaChartLine, FaBoxOpen, FaReceipt) - Shell: adicionados todos os links de nav para owner/seller no header (Estoque, Buscar Produtos, Pedidos, Carteira, Equipe, Config. Entrega) - Wallet: ícone FaMoneyCheck no botão Solicitar Saque, card saldo com #0F4C81, thead da tabela com #0F4C81, fix R$ NaN (formatCurrency null-safe) - Team: botões e thead com #0F4C81, emojis removidos dos roleLabels - ShippingSettings: wrapped com Shell (mantém header), emojis substituídos por react-icons pretos (FaTruck, FaLocationDot, FaStore, FaCircleInfo, FaFloppyDisk), botão Salvar com #0F4C81 - Orders: removido box cinza de fundo dos ícones nas abas e estado vazio - LocationPicker: fallback seguro para OpenStreetMap quando VITE_MAP_TILE_LAYER não está definido (corrige tela branca em /search) - Inventory/Cart: cores dos botões e thead atualizadas para #0F4C81
63 lines
2.3 KiB
TypeScript
63 lines
2.3 KiB
TypeScript
import { MapContainer, TileLayer, Marker, useMapEvents } from 'react-leaflet'
|
|
import { useState } from 'react'
|
|
import L from 'leaflet'
|
|
import 'leaflet/dist/leaflet.css'
|
|
|
|
// Fix generic Leaflet icon missing in webpack/vite
|
|
import icon from 'leaflet/dist/images/marker-icon.png'
|
|
import iconShadow from 'leaflet/dist/images/marker-shadow.png'
|
|
|
|
const DefaultIcon = L.icon({
|
|
iconUrl: icon,
|
|
shadowUrl: iconShadow,
|
|
iconSize: [25, 41],
|
|
iconAnchor: [12, 41]
|
|
})
|
|
|
|
L.Marker.prototype.options.icon = DefaultIcon
|
|
|
|
// Use env vars with safe fallback to OpenStreetMap
|
|
const TILE_URL = import.meta.env.VITE_MAP_TILE_LAYER ||
|
|
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
|
|
const TILE_ATTR = import.meta.env.VITE_MAP_ATTRIBUTION ||
|
|
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
|
|
|
interface LocationPickerProps {
|
|
initialLat?: number
|
|
initialLng?: number
|
|
onLocationSelect: (lat: number, lng: number) => void
|
|
}
|
|
|
|
const LocationMarker = ({ onLocationSelect }: { onLocationSelect: (lat: number, lng: number) => void }) => {
|
|
const [position, setPosition] = useState<L.LatLng | null>(null)
|
|
|
|
const map = useMapEvents({
|
|
click(e) {
|
|
setPosition(e.latlng)
|
|
onLocationSelect(e.latlng.lat, e.latlng.lng)
|
|
map.flyTo(e.latlng, map.getZoom())
|
|
},
|
|
})
|
|
|
|
return position === null ? null : (
|
|
<Marker position={position} />
|
|
)
|
|
}
|
|
|
|
export const LocationPicker = ({ initialLat, initialLng, onLocationSelect }: LocationPickerProps) => {
|
|
const defaultPosition: [number, number] = [-16.3285, -48.9534] // Anápolis center
|
|
const center = (initialLat && initialLng) ? [initialLat, initialLng] as [number, number] : defaultPosition
|
|
|
|
return (
|
|
<div className="h-[300px] w-full rounded-lg overflow-hidden border border-gray-300">
|
|
<MapContainer center={center} zoom={13} scrollWheelZoom={true} style={{ height: '100%', width: '100%' }}>
|
|
<TileLayer
|
|
attribution={TILE_ATTR}
|
|
url={TILE_URL}
|
|
/>
|
|
<LocationMarker onLocationSelect={onLocationSelect} />
|
|
{(initialLat && initialLng) && <Marker position={[initialLat, initialLng]} />}
|
|
</MapContainer>
|
|
</div>
|
|
)
|
|
}
|