mirror of
https://github.com/ceratic/project_vollidioten_website.git
synced 2026-05-14 00:16:47 +02:00
feat: Add DatabaseManager and LinkPlayer components, implement authentication and linking logic
- Created DatabaseManager component for managing database access via phpMyAdmin. - Developed LinkPlayer component to link Discord accounts with game characters, including user authentication and error handling. - Added mock data files for players, organizations, and projects to handle backend unavailability. - Implemented AuthService for managing user authentication and session checks. - Created DatabaseService to fetch and manage player, organization, and project data with fallback to mock data. - Added HTML page for handling authentication unavailability. - Developed a test script for validating Docker setup and required files.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { MOCK_ORGS } from '../constants';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Organization } from '../types';
|
||||
import { Icons } from '../components/IconSet';
|
||||
import { dbService } from '../services/DatabaseService';
|
||||
|
||||
interface CitiesProps {
|
||||
onSelectCity: (id: string) => void;
|
||||
@@ -48,7 +48,55 @@ const CityCard = ({ city, onClick }: { city: Organization; onClick: () => void }
|
||||
);
|
||||
|
||||
const Cities: React.FC<CitiesProps> = ({ onSelectCity }) => {
|
||||
const cities = MOCK_ORGS.filter(org => org.type === 'City');
|
||||
const [cities, setCities] = useState<Organization[]>([]);
|
||||
const [citiesWithStats, setCitiesWithStats] = useState<any[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const loadCities = () => {
|
||||
// Get all organizations from database
|
||||
const allOrgs = dbService.getOrgs();
|
||||
const cityOrgs = allOrgs.filter(org => org.type === 'City');
|
||||
|
||||
// Calculate dynamic stats for each city
|
||||
const citiesStats = cityOrgs.map(city => {
|
||||
// Count citizens (players with this organizationId)
|
||||
const allPlayers = dbService.getPlayers();
|
||||
const citizenCount = allPlayers.filter(player =>
|
||||
player.stats.organizationId === city.id
|
||||
).length;
|
||||
|
||||
// Count businesses/projects in this city
|
||||
const allProjects = dbService.getProjects();
|
||||
const businessCount = allProjects.filter(project =>
|
||||
project.associatedOrgId === city.id
|
||||
).length;
|
||||
|
||||
return {
|
||||
...city,
|
||||
memberCount: citizenCount,
|
||||
businessCount: businessCount,
|
||||
// Override static memberCount with dynamic count
|
||||
stats: {
|
||||
citizens: citizenCount,
|
||||
businesses: businessCount,
|
||||
...city.cityStats
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
setCities(cityOrgs);
|
||||
setCitiesWithStats(citiesStats);
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
// Initial load
|
||||
loadCities();
|
||||
|
||||
// Subscribe to updates
|
||||
const unsub = dbService.subscribe(loadCities);
|
||||
return unsub;
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="animate-in fade-in slide-in-from-bottom-2 space-y-8">
|
||||
@@ -57,19 +105,29 @@ const Cities: React.FC<CitiesProps> = ({ onSelectCity }) => {
|
||||
<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>
|
||||
{loading ? (
|
||||
<div className="flex justify-center py-20">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-accentInfo"></div>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div className="grid grid-cols-1 gap-6">
|
||||
{citiesWithStats.map(city => (
|
||||
<div key={city.id}>
|
||||
<CityCard city={city} onClick={() => onSelectCity(city.id)} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{cities.length === 0 && (
|
||||
<div className="text-center py-20 text-textMuted">
|
||||
<p>Noch keine Städte gegründet.</p>
|
||||
</div>
|
||||
{citiesWithStats.length === 0 && (
|
||||
<div className="text-center py-20 text-textMuted">
|
||||
<p>Noch keine Städte gegründet.</p>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Cities;
|
||||
export default Cities;
|
||||
|
||||
Reference in New Issue
Block a user