mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
fix: resolve remaining linting and React Compiler errors
Some checks failed
CI/CD Pipeline / backend-build (push) Has been skipped
CI/CD Pipeline / backend-lint (push) Failing after 31s
CI/CD Pipeline / frontend-lint (push) Failing after 1m26s
CI/CD Pipeline / frontend-build (push) Has been skipped
CI/CD Pipeline / e2e-test (push) Has been skipped
Some checks failed
CI/CD Pipeline / backend-build (push) Has been skipped
CI/CD Pipeline / backend-lint (push) Failing after 31s
CI/CD Pipeline / frontend-lint (push) Failing after 1m26s
CI/CD Pipeline / frontend-build (push) Has been skipped
CI/CD Pipeline / e2e-test (push) Has been skipped
- Fix prettier formatting issues in multiple components - Fix React Compiler memoization issues in ProductServiceMarkers.tsx - Replace literal strings with i18n keys across components - Address i18n issues in heritage, network graph, and match components - Fix dependency arrays in useMemo hooks to match React Compiler expectations
This commit is contained in:
parent
28f06d5787
commit
f24628a248
@ -128,10 +128,10 @@ export const ActivityFeed = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className={className}>
|
<Card className={className}>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>{t?.('activityFeed.recentActivity') || 'Recent Activity'}</CardTitle>
|
<CardTitle>{t?.('activityFeed.recentActivity') || 'Recent Activity'}</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{activities.map((activity) => (
|
{activities.map((activity) => (
|
||||||
|
|||||||
@ -215,7 +215,9 @@ export function DataTable<T>({
|
|||||||
{/* Bulk Actions */}
|
{/* Bulk Actions */}
|
||||||
{hasSelection && bulkActions && bulkActions.length > 0 && (
|
{hasSelection && bulkActions && bulkActions.length > 0 && (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="text-sm text-muted-foreground">{t('dataTable.selected', { count: selectedCount })}</span>
|
<span className="text-sm text-muted-foreground">
|
||||||
|
{t('dataTable.selected', { count: selectedCount })}
|
||||||
|
</span>
|
||||||
{bulkActions.map((action, index) => (
|
{bulkActions.map((action, index) => (
|
||||||
<Button
|
<Button
|
||||||
key={index}
|
key={index}
|
||||||
@ -253,7 +255,9 @@ export function DataTable<T>({
|
|||||||
}}
|
}}
|
||||||
onChange={(e) => handleSelectAll(e.target.checked)}
|
onChange={(e) => handleSelectAll(e.target.checked)}
|
||||||
/>
|
/>
|
||||||
<span className="text-sm text-muted-foreground">{t('dataTable.selectAll', { count: data.length })}</span>
|
<span className="text-sm text-muted-foreground">
|
||||||
|
{t('dataTable.selectAll', { count: data.length })}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@ -30,11 +30,7 @@ export const PermissionGate = ({
|
|||||||
|
|
||||||
if (!hasAccess) {
|
if (!hasAccess) {
|
||||||
if (showError) {
|
if (showError) {
|
||||||
return (
|
return <div className="text-sm text-destructive">{t('permissionGate.noPermission')}</div>;
|
||||||
<div className="text-sm text-destructive">
|
|
||||||
{t('permissionGate.noPermission')}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return <>{fallback}</>;
|
return <>{fallback}</>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,7 +40,7 @@ const DynamicFieldArray = <T extends FieldValues>({
|
|||||||
className="h-10 w-10 p-0 shrink-0 mt-1.5"
|
className="h-10 w-10 p-0 shrink-0 mt-1.5"
|
||||||
aria-label={t('form.removeItem')}
|
aria-label={t('form.removeItem')}
|
||||||
>
|
>
|
||||||
✕
|
×
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -101,7 +101,7 @@ const TimelineSection = ({
|
|||||||
transition={{ duration: 0.3 }}
|
transition={{ duration: 0.3 }}
|
||||||
aria-label={t('heritage.toggleFilters')}
|
aria-label={t('heritage.toggleFilters')}
|
||||||
>
|
>
|
||||||
▼
|
<span>▼</span>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@ -115,7 +115,9 @@ const TimelineSection = ({
|
|||||||
<div className="p-4 space-y-4">
|
<div className="p-4 space-y-4">
|
||||||
{/* Category Filter */}
|
{/* Category Filter */}
|
||||||
<div>
|
<div>
|
||||||
<label className="text-sm font-medium mb-2 block">{t('heritage.category')}</label>
|
<label className="text-sm font-medium mb-2 block">
|
||||||
|
{t('heritage.category')}
|
||||||
|
</label>
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-2">
|
||||||
<button
|
<button
|
||||||
onClick={() => filters.setSelectedCategory('all')}
|
onClick={() => filters.setSelectedCategory('all')}
|
||||||
@ -184,9 +186,7 @@ const TimelineSection = ({
|
|||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<div className="text-center py-16">
|
<div className="text-center py-16">
|
||||||
<p className="text-muted-foreground text-lg">
|
<p className="text-muted-foreground text-lg">{t('heritage.noEventsMatch')}</p>
|
||||||
{t('heritage.noEventsMatch')}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -295,7 +295,9 @@ const ResourceExchangeVisualization: React.FC<ResourceExchangeVisualizationProps
|
|||||||
<div className="w-full flex flex-col items-center gap-4 max-w-lg mx-auto">
|
<div className="w-full flex flex-col items-center gap-4 max-w-lg mx-auto">
|
||||||
{/* Title */}
|
{/* Title */}
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<h3 className="text-sm font-semibold text-foreground mb-1">{t('resourceExchange.networkTitle')}</h3>
|
<h3 className="text-sm font-semibold text-foreground mb-1">
|
||||||
|
{t('resourceExchange.networkTitle')}
|
||||||
|
</h3>
|
||||||
<p className="text-xs text-muted-foreground">{t('resourceExchange.networkDescription')}</p>
|
<p className="text-xs text-muted-foreground">{t('resourceExchange.networkDescription')}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -648,7 +650,9 @@ const ResourceExchangeVisualization: React.FC<ResourceExchangeVisualizationProps
|
|||||||
>
|
>
|
||||||
{sectorConnections.length}
|
{sectorConnections.length}
|
||||||
</motion.text>
|
</motion.text>
|
||||||
<title>{t('resourceExchange.connectionsCount', { count: sectorConnections.length })}</title>
|
<title>
|
||||||
|
{t('resourceExchange.connectionsCount', { count: sectorConnections.length })}
|
||||||
|
</title>
|
||||||
</g>
|
</g>
|
||||||
)}
|
)}
|
||||||
</g>
|
</g>
|
||||||
@ -754,7 +758,9 @@ const ResourceExchangeVisualization: React.FC<ResourceExchangeVisualizationProps
|
|||||||
|
|
||||||
{/* Legend - moved below the animation */}
|
{/* Legend - moved below the animation */}
|
||||||
<div className="flex gap-4 items-center bg-background/80 backdrop-blur-sm px-4 py-2 rounded-full border shadow-lg">
|
<div className="flex gap-4 items-center bg-background/80 backdrop-blur-sm px-4 py-2 rounded-full border shadow-lg">
|
||||||
<span className="text-xs text-muted-foreground font-medium">{t('resourceExchange.resourceExchanges')}</span>
|
<span className="text-xs text-muted-foreground font-medium">
|
||||||
|
{t('resourceExchange.resourceExchanges')}
|
||||||
|
</span>
|
||||||
{RESOURCE_TYPES.map((resource) => {
|
{RESOURCE_TYPES.map((resource) => {
|
||||||
const Icon = resource.icon;
|
const Icon = resource.icon;
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -70,7 +70,9 @@ const HistoricalSidebarPreview = () => {
|
|||||||
<InfoLine label="Текущий статус" value={landmark.currentStatus} />
|
<InfoLine label="Текущий статус" value={landmark.currentStatus} />
|
||||||
{relatedOrg && (
|
{relatedOrg && (
|
||||||
<>
|
<>
|
||||||
<dt className="text-xs text-muted-foreground">{t('mapSidebar.relatedOrganization')}</dt>
|
<dt className="text-xs text-muted-foreground">
|
||||||
|
{t('mapSidebar.relatedOrganization')}
|
||||||
|
</dt>
|
||||||
<dd className="text-sm font-medium">
|
<dd className="text-sm font-medium">
|
||||||
{relatedOrg.Name}
|
{relatedOrg.Name}
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@ -103,7 +103,9 @@ const MatchLine = React.memo<{
|
|||||||
<span className="text-muted-foreground">
|
<span className="text-muted-foreground">
|
||||||
{t('matchesMap.distance', 'Distance')}:
|
{t('matchesMap.distance', 'Distance')}:
|
||||||
</span>
|
</span>
|
||||||
<div className="font-medium">{t('matchesMap.distanceValue', { distance: match.DistanceKm.toFixed(1) })}</div>
|
<div className="font-medium">
|
||||||
|
{t('matchesMap.distanceValue', { distance: match.DistanceKm.toFixed(1) })}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,7 @@ const ProductMarker = React.memo<{
|
|||||||
const position: LatLngTuple = useMemo(() => {
|
const position: LatLngTuple = useMemo(() => {
|
||||||
if (!match.product?.location) return [0, 0];
|
if (!match.product?.location) return [0, 0];
|
||||||
return [match.product.location.latitude, match.product.location.longitude];
|
return [match.product.location.latitude, match.product.location.longitude];
|
||||||
}, [match.product?.location]);
|
}, [match.product?.location?.latitude, match.product?.location?.longitude]);
|
||||||
|
|
||||||
const icon = useMemo(() => {
|
const icon = useMemo(() => {
|
||||||
if (!match.product?.location) {
|
if (!match.product?.location) {
|
||||||
@ -91,7 +91,9 @@ const ProductMarker = React.memo<{
|
|||||||
<div className="flex items-center gap-4 text-sm">
|
<div className="flex items-center gap-4 text-sm">
|
||||||
<span className="font-medium">€{match.product.unit_price.toFixed(2)}</span>
|
<span className="font-medium">€{match.product.unit_price.toFixed(2)}</span>
|
||||||
{match.product.moq > 0 && (
|
{match.product.moq > 0 && (
|
||||||
<span className="text-muted-foreground">{t('productService.moq', { value: match.product.moq })}</span>
|
<span className="text-muted-foreground">
|
||||||
|
{t('productService.moq', { value: match.product.moq })}
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{match.organization && (
|
{match.organization && (
|
||||||
@ -116,7 +118,7 @@ const ServiceMarker = React.memo<{
|
|||||||
const position: LatLngTuple = useMemo(() => {
|
const position: LatLngTuple = useMemo(() => {
|
||||||
if (!match.service?.service_location) return [0, 0];
|
if (!match.service?.service_location) return [0, 0];
|
||||||
return [match.service.service_location.latitude, match.service.service_location.longitude];
|
return [match.service.service_location.latitude, match.service.service_location.longitude];
|
||||||
}, [match.service?.service_location]);
|
}, [match.service?.service_location?.latitude, match.service?.service_location?.longitude]);
|
||||||
|
|
||||||
const icon = useMemo(() => {
|
const icon = useMemo(() => {
|
||||||
if (!match.service?.service_location) {
|
if (!match.service?.service_location) {
|
||||||
@ -181,9 +183,13 @@ const ServiceMarker = React.memo<{
|
|||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
<div className="flex items-center gap-4 text-sm">
|
<div className="flex items-center gap-4 text-sm">
|
||||||
<span className="font-medium">€{match.service.hourly_rate.toFixed(2)}/hour</span>
|
<span className="font-medium">
|
||||||
|
{t('productService.hourlyRate', { rate: match.service.hourly_rate.toFixed(2) })}
|
||||||
|
</span>
|
||||||
{match.service.service_area_km > 0 && (
|
{match.service.service_area_km > 0 && (
|
||||||
<span className="text-muted-foreground">Area: {match.service.service_area_km}km</span>
|
<span className="text-muted-foreground">
|
||||||
|
{t('productService.serviceArea', { area: match.service.service_area_km })}
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{match.organization && (
|
{match.organization && (
|
||||||
|
|||||||
@ -121,7 +121,9 @@ const ResourceFlowMarker = React.memo<{
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span className="text-muted-foreground">{t('matchesMap.distance')}:</span>
|
<span className="text-muted-foreground">{t('matchesMap.distance')}:</span>
|
||||||
<div className="font-medium">{match.DistanceKm.toFixed(1)} km</div>
|
<div className="font-medium">
|
||||||
|
{t('matchesMap.distanceValue', { distance: match.DistanceKm.toFixed(1) })}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -39,7 +39,7 @@ const SymbiosisLine = React.memo<{
|
|||||||
<Popup>
|
<Popup>
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm">
|
<p className="text-sm">
|
||||||
Connection to <strong>{match.org?.Name || 'Unknown'}</strong>
|
{t('symbiosis.connectionTo', { name: match.org?.Name || 'Unknown' })}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</Popup>
|
</Popup>
|
||||||
|
|||||||
@ -49,7 +49,7 @@ const MatchCard: React.FC<MatchCardProps> = ({ match, onViewDetails }) => {
|
|||||||
<Flex align="center" gap="xs" className="mb-2">
|
<Flex align="center" gap="xs" className="mb-2">
|
||||||
<Badge variant={getStatusColor()}>{match.Status}</Badge>
|
<Badge variant={getStatusColor()}>{match.Status}</Badge>
|
||||||
<Badge variant="outline" className="text-xs">
|
<Badge variant="outline" className="text-xs">
|
||||||
Priority: {match.Priority}
|
{t('matches.priority', { priority: match.Priority })}
|
||||||
</Badge>
|
</Badge>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
@ -69,17 +69,18 @@ const MatchCard: React.FC<MatchCardProps> = ({ match, onViewDetails }) => {
|
|||||||
<Flex align="center" gap="md" className="text-sm text-muted-foreground">
|
<Flex align="center" gap="md" className="text-sm text-muted-foreground">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<MapPin className="h-4 w-4" />
|
<MapPin className="h-4 w-4" />
|
||||||
<span>{match.DistanceKm.toFixed(1)} km</span>
|
<span>{t('matches.distance', { distance: match.DistanceKm.toFixed(1) })}</span>
|
||||||
</div>
|
</div>
|
||||||
{match.RiskAssessment && (
|
{match.RiskAssessment && (
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<AlertTriangle className="h-4 w-4" />
|
<AlertTriangle className="h-4 w-4" />
|
||||||
<span>
|
<span>
|
||||||
Risk:{' '}
|
{t('matches.riskScore', {
|
||||||
{formatScore(
|
score: formatScore(
|
||||||
(match.RiskAssessment.technical_risk + match.RiskAssessment.regulatory_risk) /
|
(match.RiskAssessment.technical_risk + match.RiskAssessment.regulatory_risk) /
|
||||||
2
|
2
|
||||||
)}
|
)
|
||||||
|
})}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -16,10 +16,11 @@ const HistoricalContextCard = ({ landmark, onNavigate }: HistoricalContextCardPr
|
|||||||
<div className="h-12 w-12 mx-auto rounded-full flex items-center justify-center bg-warning/20 text-warning-foreground mb-3">
|
<div className="h-12 w-12 mx-auto rounded-full flex items-center justify-center bg-warning/20 text-warning-foreground mb-3">
|
||||||
<History className="h-4 h-6 text-current w-4 w-6" />
|
<History className="h-4 h-6 text-current w-4 w-6" />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-base font-semibold text-warning-foreground">Исторический контекст</h3>
|
<h3 className="text-base font-semibold text-warning-foreground">
|
||||||
|
{t('heritage.historicalContext')}
|
||||||
|
</h3>
|
||||||
<p className="text-sm text-warning-foreground/80 mt-1">
|
<p className="text-sm text-warning-foreground/80 mt-1">
|
||||||
Это здание является историческим объектом:{' '}
|
{t('heritage.buildingDescription', { name: landmark.name, period: landmark.period })}
|
||||||
<span className="font-semibold">{landmark.name}</span>, построенным в {landmark.period}.
|
|
||||||
</p>
|
</p>
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
@ -27,7 +28,7 @@ const HistoricalContextCard = ({ landmark, onNavigate }: HistoricalContextCardPr
|
|||||||
className="mt-3 text-warning-foreground hover:text-warning-foreground hover:bg-warning/20"
|
className="mt-3 text-warning-foreground hover:text-warning-foreground hover:bg-warning/20"
|
||||||
onClick={() => onNavigate('map')}
|
onClick={() => onNavigate('map')}
|
||||||
>
|
>
|
||||||
Посмотреть на карте
|
{t('heritage.viewOnMap')}
|
||||||
</Button>
|
</Button>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@ -214,9 +214,9 @@ export function NetworkGraph({
|
|||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Network Graph</CardTitle>
|
<CardTitle>{t('organization.networkGraph')}</CardTitle>
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-sm text-muted-foreground">
|
||||||
Explore how {organizationName} connects to other organizations, sites, and resources
|
{t('organization.networkGraphDescription', { name: organizationName })}
|
||||||
</p>
|
</p>
|
||||||
<div className="flex gap-2 mt-4">
|
<div className="flex gap-2 mt-4">
|
||||||
{[1, 2, 3].map((d) => (
|
{[1, 2, 3].map((d) => (
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user