mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
- Remove nested git repository from bugulma/frontend/.git - Add all frontend files to main repository tracking - Convert from separate frontend/backend repos to unified monorepo - Preserve all frontend code and development history as tracked files - Eliminate nested repository complexity for simpler development workflow This creates a proper monorepo structure with frontend and backend coexisting in the same repository for easier development and deployment.
94 lines
2.5 KiB
TypeScript
94 lines
2.5 KiB
TypeScript
import { LatLngTuple } from 'leaflet';
|
|
import React, { useCallback } from 'react';
|
|
import { Marker, Popup } from 'react-leaflet';
|
|
import { useMapActions } from '@/contexts/MapContexts.tsx';
|
|
import { HistoricalLandmark } from '@/types.ts';
|
|
import { getCachedHistoricalIcon } from '@/utils/map/iconCache.ts';
|
|
|
|
interface HistoricalMarkersProps {
|
|
landmarks: HistoricalLandmark[];
|
|
selectedLandmark: HistoricalLandmark | null;
|
|
hoveredLandmarkId: string | null;
|
|
}
|
|
|
|
/**
|
|
* Individual historical marker component memoized to prevent unnecessary re-renders
|
|
*/
|
|
const HistoricalMarker = React.memo<{
|
|
landmark: HistoricalLandmark;
|
|
isSelected: boolean;
|
|
isHovered: boolean;
|
|
onSelect: (landmark: HistoricalLandmark) => void;
|
|
onHover: (landmarkId: string | null) => void;
|
|
}>(({ landmark, isSelected, isHovered, onSelect, onHover }) => {
|
|
const position: LatLngTuple = [landmark.location.lat, landmark.location.lng];
|
|
const icon = getCachedHistoricalIcon(landmark.id, landmark, isSelected, isHovered);
|
|
|
|
const handleClick = useCallback(() => {
|
|
onSelect(landmark);
|
|
}, [landmark, onSelect]);
|
|
|
|
const handleMouseOver = useCallback(() => {
|
|
onHover(landmark.id);
|
|
}, [landmark.id, onHover]);
|
|
|
|
const handleMouseOut = useCallback(() => {
|
|
onHover(null);
|
|
}, [onHover]);
|
|
|
|
if (!landmark.location) return null;
|
|
|
|
return (
|
|
<Marker
|
|
position={position}
|
|
icon={icon}
|
|
eventHandlers={{
|
|
click: handleClick,
|
|
mouseover: handleMouseOver,
|
|
mouseout: handleMouseOut,
|
|
}}
|
|
>
|
|
<Popup>
|
|
<div>
|
|
<h3 className="text-base font-semibold">{landmark.name}</h3>
|
|
<p className="text-sm text-muted-foreground">{landmark.period}</p>
|
|
</div>
|
|
</Popup>
|
|
</Marker>
|
|
);
|
|
});
|
|
|
|
HistoricalMarker.displayName = 'HistoricalMarker';
|
|
|
|
const HistoricalMarkers: React.FC<HistoricalMarkersProps> = ({
|
|
landmarks,
|
|
selectedLandmark,
|
|
hoveredLandmarkId,
|
|
}) => {
|
|
const { handleSelectLandmark, setHoveredLandmarkId } = useMapActions();
|
|
|
|
return (
|
|
<>
|
|
{landmarks.map((landmark) => {
|
|
if (!landmark.location) return null;
|
|
|
|
const isSelected = selectedLandmark?.id === landmark.id;
|
|
const isHovered = hoveredLandmarkId === landmark.id;
|
|
|
|
return (
|
|
<HistoricalMarker
|
|
key={landmark.id}
|
|
landmark={landmark}
|
|
isSelected={isSelected}
|
|
isHovered={isHovered}
|
|
onSelect={handleSelectLandmark}
|
|
onHover={setHoveredLandmarkId}
|
|
/>
|
|
);
|
|
})}
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default React.memo(HistoricalMarkers);
|