feat: Initialize project with Vite, React, and TypeScript

Sets up the foundational structure for the Obsidian | RP Plattform. This includes configuring Vite as the build tool, integrating React for the UI, and establishing TypeScript for type safety. Also includes initial styling and placeholder data to define the application's core interfaces.
This commit is contained in:
Lars Behrends
2025-12-28 02:15:09 +01:00
parent 4ab4a1d64a
commit d1b797a320
23 changed files with 2514 additions and 8 deletions

75
pages/Cities.tsx Normal file
View File

@@ -0,0 +1,75 @@
import React from 'react';
import { MOCK_ORGS } from '../constants';
import { Organization } from '../types';
import { Icons } from '../components/IconSet';
interface CitiesProps {
onSelectCity: (id: string) => void;
}
const CityCard = ({ city, onClick }: { city: Organization; onClick: () => void }) => (
<div
onClick={onClick}
className="group relative h-64 rounded-2xl overflow-hidden cursor-pointer border border-border hover:border-accentInfo/50 transition-all duration-300 shadow-card"
>
{/* Background Image */}
<div className="absolute inset-0">
<img
src={city.bannerUrl || 'https://via.placeholder.com/800x400'}
alt={city.name}
className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-105"
/>
<div className="absolute inset-0 bg-gradient-to-t from-background via-background/60 to-transparent" />
</div>
{/* Content */}
<div className="absolute inset-0 p-6 flex flex-col justify-end">
<div className="flex justify-between items-end">
<div>
<div className="text-xs font-bold text-accentInfo mb-1 uppercase tracking-widest">{city.establishedYear || 'Unbekannte Ära'}</div>
<h2 className="text-3xl font-bold text-white mb-2 group-hover:translate-x-1 transition-transform">{city.name}</h2>
<p className="text-sm text-gray-300 line-clamp-2 max-w-sm">
{city.description}
</p>
</div>
<div className="flex flex-col items-end gap-2">
<div className="flex items-center gap-2 px-3 py-1 bg-black/40 backdrop-blur rounded-full border border-white/10">
<Icons.Users className="w-4 h-4 text-textMuted" />
<span className="text-sm font-medium text-white">{city.memberCount} Bürger</span>
</div>
<div className="px-3 py-1 bg-accentInfo/20 backdrop-blur rounded-full border border-accentInfo/30 text-xs font-bold text-accentInfo uppercase">
{city.status}
</div>
</div>
</div>
</div>
</div>
);
const Cities: React.FC<CitiesProps> = ({ onSelectCity }) => {
const cities = MOCK_ORGS.filter(org => org.type === 'City');
return (
<div className="animate-in fade-in slide-in-from-bottom-2 space-y-8">
<div>
<h1 className="text-3xl font-bold mb-1">Große Siedlungen</h1>
<p className="text-textMuted">Entdecke die blühenden Zentren der Zivilisation im Obsidian-Tal.</p>
</div>
<div className="grid grid-cols-1 gap-6">
{cities.map(city => (
<CityCard key={city.id} city={city} onClick={() => onSelectCity(city.id)} />
))}
</div>
{cities.length === 0 && (
<div className="text-center py-20 text-textMuted">
<p>Noch keine Städte gegründet.</p>
</div>
)}
</div>
);
};
export default Cities;