Files
project_vollidioten_website/pages/ProjectProfile.tsx

708 lines
37 KiB
TypeScript

import React, { useState, useEffect } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { Project, ShopItem } from '../types';
import { Icons, ItemIcon } from '../components/IconSet';
import { dbService } from '../services/DatabaseService';
import { authService } from '../services/AuthService';
import { DiscordUser } from '../types';
import EditModal from '../components/EditModal';
import ShopManagementModal from '../components/ShopManagementModal';
import EmployeeManagementModal from '../components/EmployeeManagementModal';
import BannerManagementModal from '../components/BannerManagementModal';
import LogoManagementModal from '../components/LogoManagementModal';
import GalleryManagementModal from '../components/GalleryManagementModal';
import DeleteProjectModal from '../components/DeleteProjectModal';
const ProjectProfile: React.FC = () => {
const { id } = useParams<{ id: string }>();
const navigate = useNavigate();
const [project, setProject] = useState<Project | null>(null);
const [loading, setLoading] = useState(true);
const [activeTab, setActiveTab] = useState<'overview' | 'shop' | 'manage'>('overview');
const [user, setUser] = useState<DiscordUser | null>(null);
const [org, setOrg] = useState<any>(null);
const [ownerPlayer, setOwnerPlayer] = useState<any>(null);
const [isEditDescriptionOpen, setIsEditDescriptionOpen] = useState(false);
const [isEditHiringOpen, setIsEditHiringOpen] = useState(false);
const [isShopModalOpen, setIsShopModalOpen] = useState(false);
const [isEmployeeModalOpen, setIsEmployeeModalOpen] = useState(false);
const [isBannerModalOpen, setIsBannerModalOpen] = useState(false);
const [isLogoModalOpen, setIsLogoModalOpen] = useState(false);
const [isGalleryModalOpen, setIsGalleryModalOpen] = useState(false);
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
// Subscribe to auth and data updates
useEffect(() => {
const unsubAuth = authService.subscribe(setUser);
return unsubAuth;
}, []);
useEffect(() => {
if (!id) {
navigate('/projects');
return;
}
// Load project data
const projectData = dbService.getProject(id);
if (projectData) {
setProject(projectData);
} else {
navigate('/projects');
return;
}
setLoading(false);
}, [id, navigate]);
useEffect(() => {
if (!project) return;
// Load associated org and owner player
if (project.associatedOrgId) {
const foundOrg = dbService.getOrg(project.associatedOrgId);
setOrg(foundOrg);
}
// Find owner player by username
const players = dbService.getPlayers();
const owner = players.find(p => p.username === project.owner);
setOwnerPlayer(owner);
}, [project]);
const onSelectPlayer = (playerId: string) => navigate(`/players/${playerId}`);
const onSelectOrg = (orgId: string) => {
const org = dbService.getOrgs().find(o => o.id === orgId);
if (org?.type === 'City') {
navigate(`/cities/${orgId}`);
} else {
navigate(`/organizations/${orgId}`);
}
};
const onBack = () => navigate('/projects');
const hasShop = project?.shopCatalog && project.shopCatalog.length > 0;
const isOwner = user?.linkedPlayerUuid && ownerPlayer && dbService.getPlayer(user.linkedPlayerUuid)?.username === project?.owner;
// Group shop items
const services = project?.shopCatalog?.filter(i => i.type === 'service') || [];
const products = project?.shopCatalog?.filter(i => i.type !== 'service') || [];
if (loading || !project) {
return (
<div className="max-w-4xl mx-auto animate-in slide-in-from-right-4 duration-300">
<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>
);
}
return (
<div className="animate-in slide-in-from-right-4 duration-300">
<button onClick={() => navigate('/projects')} className="flex items-center gap-2 text-sm text-textMuted hover:text-textMain mb-6 transition-colors group">
<span className="group-hover:-translate-x-1 transition-transform"></span> Zurück zum Verzeichnis
</button>
{/* Banner Header */}
<div className="relative h-64 md:h-80 rounded-2xl overflow-hidden border border-border mb-8 shadow-card group">
<img
src={project.bannerUrl || 'https://images.unsplash.com/photo-1542601906990-b4d3fb778b09?q=80&w=2070&auto=format&fit=crop'}
alt={project.title}
className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-105"
/>
{/* Decorative elements for Black Market */}
{project.category === 'Black Market' && (
<div className="absolute inset-0 bg-red-900/20 mix-blend-overlay" />
)}
<div className="absolute inset-0 bg-gradient-to-t from-background via-background/80 to-transparent" />
<div className="absolute bottom-0 left-0 right-0 p-8">
<div className="flex flex-col md:flex-row md:items-end justify-between gap-4">
<div>
<div className="flex items-center gap-2 mb-2">
<span className={`text-xs font-mono px-2 py-1 rounded border border-white/5 uppercase tracking-wider bg-black/40 backdrop-blur ${
project.category === 'Story Arc' ? 'text-orange-400' :
project.category === 'Black Market' ? 'text-red-400' :
'text-accentInfo'
}`}>
{project.category}
</span>
{project.status === 'active' && (
<span className="flex items-center gap-1.5 text-xs font-bold text-accentSuccess bg-black/40 px-2 py-1 rounded backdrop-blur border border-white/5">
<span className="w-1.5 h-1.5 rounded-full bg-accentSuccess animate-pulse" />
AKTIV
</span>
)}
{project.hiring && (
<span className="flex items-center gap-1.5 text-xs font-bold text-purple-400 bg-black/40 px-2 py-1 rounded backdrop-blur border border-white/5">
<span className="w-1.5 h-1.5 rounded-full bg-purple-400 animate-pulse" />
STELLEN
</span>
)}
</div>
<h1 className="text-4xl md:text-5xl font-bold text-white tracking-tight mb-2 drop-shadow-lg">{project.title}</h1>
<div className="flex items-center gap-6 text-sm text-gray-300">
<span
className={`flex items-center gap-2 ${ownerPlayer ? 'cursor-pointer hover:text-white transition-colors group/owner' : ''}`}
onClick={() => ownerPlayer && onSelectPlayer(ownerPlayer.uuid)}
>
{project.logoUrl ? (
<img
src={project.logoUrl}
alt={`${project.title} Logo`}
className="w-5 h-5 rounded-full border border-white/10 object-cover group-hover/owner:border-accentInfo transition-colors"
/>
) : (
<div className="w-5 h-5 rounded-full bg-gradient-to-br from-gray-700 to-gray-900 flex items-center justify-center text-[10px] border border-white/10 font-bold group-hover/owner:border-accentInfo group-hover/owner:text-accentInfo transition-colors">
{project.owner.charAt(0)}
</div>
)}
Inhaber: <span className="text-white font-medium group-hover/owner:underline decoration-accentInfo/50 underline-offset-4">{project.owner}</span>
</span>
{project.foundedDate && (
<span className="flex items-center gap-1.5 text-textMuted">
<Icons.Layers className="w-3.5 h-3.5" /> Gegr. {project.foundedDate}
</span>
)}
</div>
</div>
{hasShop && (
<button
onClick={() => setActiveTab('shop')}
className="flex items-center gap-2 bg-accentInfo hover:bg-accentInfo/90 text-white px-6 py-3 rounded-lg font-medium transition-colors shadow-lg shadow-accentInfo/20 border border-white/10 backdrop-blur-sm group/btn"
>
<Icons.ShoppingBag className="w-4 h-4 group-hover/btn:scale-110 transition-transform" />
Katalog öffnen
</button>
)}
</div>
</div>
</div>
{/* Navigation */}
<div className="flex gap-8 border-b border-border mb-8 px-2">
<button
onClick={() => setActiveTab('overview')}
className={`pb-4 text-sm font-medium transition-colors border-b-2 ${activeTab === 'overview' ? 'border-accentInfo text-white' : 'border-transparent text-textMuted hover:text-white'}`}
>
Übersicht
</button>
{hasShop && (
<button
onClick={() => setActiveTab('shop')}
className={`pb-4 text-sm font-medium transition-colors border-b-2 ${activeTab === 'shop' ? 'border-accentInfo text-white' : 'border-transparent text-textMuted hover:text-white'}`}
>
Katalog ({project.shopCatalog?.length})
</button>
)}
{isOwner && (
<button
onClick={() => setActiveTab('manage')}
className={`pb-4 text-sm font-medium transition-colors border-b-2 ${activeTab === 'manage' ? 'border-accentInfo text-white' : 'border-transparent text-textMuted hover:text-white'}`}
>
Verwalten
</button>
)}
</div>
{/* Content */}
<div className="min-h-[400px]">
{activeTab === 'overview' && (
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
<div className="lg:col-span-2 space-y-8">
<section className="bg-surface/50 border border-border rounded-xl p-6">
<h3 className="text-lg font-bold text-white mb-4">Manifest</h3>
<p className="text-textMuted leading-relaxed whitespace-pre-line text-lg">
{project.description}
</p>
</section>
{/* Project Portfolio / Gallery */}
{project.gallery && project.gallery.length > 0 && (
<section>
<h3 className="text-lg font-bold text-white mb-4 flex items-center gap-2">
<Icons.Layers className="w-4 h-4 text-accentInfo" /> Portfolio
</h3>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
{project.gallery.map((image, idx) => (
<div key={idx} className="rounded-xl overflow-hidden aspect-video border border-border group relative">
<img src={image.url} alt={`Portfolio ${idx}`} className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-110" />
<div className="absolute inset-0 bg-black/0 group-hover:bg-black/20 transition-colors" />
</div>
))}
</div>
</section>
)}
<section>
<h3 className="text-lg font-bold text-white mb-4 flex items-center gap-2">
<Icons.Users className="w-4 h-4 text-accentInfo" /> Personal
</h3>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
{project.employees.map((emp, idx) => {
const players = dbService.getPlayers();
const empPlayer = players.find(p => p.username === emp);
return (
<div
key={idx}
onClick={() => empPlayer && onSelectPlayer(empPlayer.uuid)}
className={`flex items-center gap-3 bg-surface border border-border p-3 rounded-lg ${empPlayer ? 'cursor-pointer hover:border-accentInfo/50 hover:bg-surfaceHighlight/30 transition-all group' : ''}`}
>
<div className="w-8 h-8 bg-surfaceHighlight rounded flex items-center justify-center text-xs font-bold text-textMuted group-hover:text-textMain transition-colors">
{emp.charAt(0)}
</div>
<span className="text-sm font-medium text-gray-300 group-hover:text-accentInfo transition-colors">{emp}</span>
</div>
);
})}
{project.employees.length === 0 && (
<div className="text-textMuted italic text-sm">Kein weiteres Personal registriert.</div>
)}
</div>
</section>
</div>
{/* Right Column: Statistics */}
<div className="space-y-6">
<div className="bg-surface border border-border rounded-xl p-6 h-fit">
<h3 className="text-xs font-bold uppercase text-textMuted mb-6 flex items-center gap-2">
<Icons.Terminal className="w-4 h-4" /> Unternehmensdaten
</h3>
<div className="space-y-5">
{/* Industry */}
<div className="flex justify-between items-center">
<span className="text-sm text-textMuted">Branche</span>
<span className={`text-sm font-medium ${
project.category === 'Black Market' ? 'text-red-400' : 'text-white'
}`}>{project.category}</span>
</div>
<div className="w-full bg-white/5 h-px" />
{/* Founded */}
<div className="flex justify-between items-center">
<span className="text-sm text-textMuted">Gegründet</span>
<span className="text-sm font-medium text-white">{project.foundedDate || 'N/A'}</span>
</div>
<div className="w-full bg-white/5 h-px" />
{/* Reputation */}
<div>
<div className="flex justify-between text-xs mb-2">
<span className="text-textMuted">Ruf</span>
<span className="font-mono text-white">{project.progress}/100</span>
</div>
<div className="h-1.5 bg-surfaceHighlight rounded-full overflow-hidden">
<div
className={`h-full ${project.category === 'Black Market' ? 'bg-red-500' : 'bg-accentInfo'}`}
style={{ width: `${project.progress}%` }}
/>
</div>
</div>
<div className="w-full bg-white/5 h-px" />
{/* Workforce */}
<div className="flex justify-between items-center">
<span className="text-sm text-textMuted">Belegschaft</span>
<div className="flex items-center gap-2">
<Icons.Users className="w-3 h-3 text-textMuted" />
<span className="text-sm font-medium text-white">{project.employees.length + 1}</span>
</div>
</div>
{/* Headquarters Link */}
{org && (
<div className="mt-4 pt-4 border-t border-white/5">
<span className="text-xs text-textMuted block mb-2">Hauptsitz</span>
<div
onClick={() => onSelectOrg(org.id)}
className="flex items-center gap-3 bg-surfaceHighlight/50 p-2 rounded-lg border border-white/5 cursor-pointer hover:border-accentInfo/50 hover:bg-surfaceHighlight transition-all group"
>
<div className="w-8 h-8 rounded bg-blue-500/20 text-blue-400 flex items-center justify-center font-bold text-xs border border-blue-500/20">
{org.name.charAt(0)}
</div>
<span className="text-sm font-medium text-gray-200 group-hover:text-white transition-colors">{org.name}</span>
</div>
</div>
)}
</div>
</div>
</div>
</div>
)}
{activeTab === 'manage' && isOwner && (
<div className="space-y-8">
<div className="bg-surface/50 border border-border rounded-xl p-6">
<h3 className="text-lg font-bold text-white mb-6 flex items-center gap-2">
<Icons.Edit className="w-5 h-5 text-accentInfo" />
Unternehmen verwalten
</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{/* Edit Description */}
<div className="bg-surfaceHighlight/30 border border-border rounded-lg p-4">
<h4 className="text-sm font-semibold text-textMain mb-3">Manifest bearbeiten</h4>
<p className="text-xs text-textMuted mb-4">
Ändern Sie die Beschreibung und das Leitbild Ihres Unternehmens.
</p>
<button
onClick={() => setIsEditDescriptionOpen(true)}
className="w-full bg-accentInfo hover:bg-accentInfo/90 text-white text-sm font-medium py-2 px-4 rounded transition-colors"
>
Beschreibung bearbeiten
</button>
</div>
{/* Toggle Hiring */}
<div className="bg-surfaceHighlight/30 border border-border rounded-lg p-4">
<h4 className="text-sm font-semibold text-textMain mb-3">Stellenanzeigen</h4>
<p className="text-xs text-textMuted mb-4">
Aktuell: {project.hiring ? 'Stellen sind ausgeschrieben' : 'Keine offenen Stellen'}
</p>
<button
onClick={() => setIsEditHiringOpen(true)}
className="w-full bg-accentInfo hover:bg-accentInfo/90 text-white text-sm font-medium py-2 px-4 rounded transition-colors"
>
{project.hiring ? 'Stellenanzeigen beenden' : 'Stellen ausschreiben'}
</button>
</div>
{/* Shop Management */}
<div className="bg-surfaceHighlight/30 border border-border rounded-lg p-4">
<h4 className="text-sm font-semibold text-textMain mb-3">Shop verwalten</h4>
<p className="text-xs text-textMuted mb-4">
Fügen Sie Produkte, Dienstleistungen und Preise hinzu.
</p>
<button
onClick={() => setIsShopModalOpen(true)}
className="w-full bg-purple-500 hover:bg-purple-600 text-white text-sm font-medium py-2 px-4 rounded transition-colors"
>
Shop bearbeiten
</button>
</div>
{/* Employee Management */}
<div className="bg-surfaceHighlight/30 border border-border rounded-lg p-4">
<h4 className="text-sm font-semibold text-textMain mb-3">Mitarbeiter verwalten</h4>
<p className="text-xs text-textMuted mb-4">
Fügen Sie Mitarbeiter hinzu oder entfernen Sie sie.
</p>
<button
onClick={() => setIsEmployeeModalOpen(true)}
className="w-full bg-green-500 hover:bg-green-600 text-white text-sm font-medium py-2 px-4 rounded transition-colors"
>
Mitarbeiter verwalten
</button>
</div>
{/* Banner Management */}
<div className="bg-surfaceHighlight/30 border border-border rounded-lg p-4">
<h4 className="text-sm font-semibold text-textMain mb-3">Banner ändern</h4>
<p className="text-xs text-textMuted mb-4">
Ändern Sie das Titelbild Ihres Unternehmens.
</p>
<button
onClick={() => setIsBannerModalOpen(true)}
className="w-full bg-orange-500 hover:bg-orange-600 text-white text-sm font-medium py-2 px-4 rounded transition-colors"
>
Banner bearbeiten
</button>
</div>
{/* Logo Management */}
<div className="bg-surfaceHighlight/30 border border-border rounded-lg p-4">
<h4 className="text-sm font-semibold text-textMain mb-3">Logo ändern</h4>
<p className="text-xs text-textMuted mb-4">
Setzen Sie ein Logo für Ihr Unternehmen.
</p>
<button
onClick={() => setIsLogoModalOpen(true)}
className="w-full bg-green-500 hover:bg-green-600 text-white text-sm font-medium py-2 px-4 rounded transition-colors"
>
Logo bearbeiten
</button>
</div>
{/* Gallery Management */}
<div className="bg-surfaceHighlight/30 border border-border rounded-lg p-4">
<h4 className="text-sm font-semibold text-textMain mb-3">Galerie verwalten</h4>
<p className="text-xs text-textMuted mb-4">
Fügen Sie Bilder zu Ihrem Portfolio hinzu.
</p>
<button
onClick={() => setIsGalleryModalOpen(true)}
className="w-full bg-blue-500 hover:bg-blue-600 text-white text-sm font-medium py-2 px-4 rounded transition-colors"
>
Galerie bearbeiten
</button>
</div>
{/* Danger Zone */}
<div className="bg-red-500/10 border border-red-500/20 rounded-lg p-4">
<h4 className="text-sm font-semibold text-red-400 mb-3">Gefahrenzone</h4>
<p className="text-xs text-red-300 mb-4">
Unwiderrufliche Aktionen für dieses Unternehmen.
</p>
<button
onClick={() => setIsDeleteModalOpen(true)}
className="w-full bg-red-500 hover:bg-red-600 text-white text-sm font-medium py-2 px-4 rounded transition-colors"
>
Unternehmen löschen
</button>
</div>
</div>
</div>
</div>
)}
{activeTab === 'shop' && project.shopCatalog && (
<div className="space-y-12">
{/* Services Section */}
{services.length > 0 && (
<section>
<div className="flex items-center gap-3 mb-6">
<div className="p-2 bg-amber-500/10 rounded-lg text-amber-400">
<Icons.Hammer className="w-5 h-5" />
</div>
<div>
<h2 className="text-xl font-bold text-white">Dienstleistungen & Verträge</h2>
<p className="text-sm text-textMuted">Fachkräfte für Spezialaufträge anheuern.</p>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{services.map(item => (
<div key={item.id} className="bg-surface border border-border rounded-xl p-6 flex flex-col hover:border-accentInfo/30 transition-all">
<div className="flex justify-between items-start mb-2">
<h3 className="text-lg font-bold text-white">{item.name}</h3>
<span className="font-mono text-accentInfo font-bold bg-accentInfo/10 px-3 py-1 rounded">
{item.price} {item.currency}
</span>
</div>
<p className="text-sm text-textMuted mb-4">{item.description}</p>
{item.materialsRequired && (
<div className="mt-auto mb-4 bg-surfaceHighlight/50 border border-white/5 rounded p-3 text-xs">
<span className="font-bold text-gray-300 block mb-1">Materialanforderungen:</span>
<span className="text-textMuted">{item.materialsRequired}</span>
</div>
)}
<button className="mt-2 w-full py-2 bg-white/5 hover:bg-white/10 rounded text-sm font-medium transition-colors border border-white/5">
Angebot anfordern
</button>
</div>
))}
</div>
</section>
)}
{/* Products Section */}
{products.length > 0 && (
<section>
<div className="flex items-center gap-3 mb-6">
<div className="p-2 bg-blue-500/10 rounded-lg text-blue-400">
<Icons.Box className="w-5 h-5" />
</div>
<div>
<h2 className="text-xl font-bold text-white">Produktkatalog</h2>
<p className="text-sm text-textMuted">Items, Bücher und Baupläne zur sofortigen Abholung.</p>
</div>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
{products.map(item => (
<div key={item.id} className="bg-surface border border-border rounded-xl p-5 hover:border-accentInfo/30 transition-all group flex flex-col">
<div className="flex justify-between items-start mb-4">
<div className="w-12 h-12 bg-surfaceHighlight rounded-lg flex items-center justify-center text-textMuted group-hover:text-accentInfo transition-colors">
{item.type === 'blueprint' ? <Icons.Scroll className="w-6 h-6" /> :
<ItemIcon type="consumable" className="w-6 h-6" />}
</div>
<div className={`px-2 py-0.5 rounded text-[10px] font-bold uppercase border ${
item.stock > 0 ? 'bg-green-500/10 text-green-400 border-green-500/20' : 'bg-red-500/10 text-red-400 border-red-500/20'
}`}>
{item.stock > 0 ? `${item.stock} auf Lager` : 'Ausverkauft'}
</div>
</div>
<h3 className="text-lg font-bold text-white mb-1">{item.name}</h3>
<p className="text-sm text-textMuted mb-4 flex-1 line-clamp-2">{item.description}</p>
<div className="mt-auto pt-4 border-t border-white/5 flex items-center justify-between">
<div className="flex flex-col">
<span className="text-[10px] text-textMuted uppercase">Preis</span>
<span className="font-mono font-bold text-accentInfo">
{item.price} <span className="text-xs font-sans text-gray-400">{item.currency}</span>
</span>
</div>
<button
disabled={item.stock === 0}
className="px-4 py-2 bg-white/5 hover:bg-white/10 disabled:opacity-50 disabled:cursor-not-allowed rounded text-sm font-medium transition-colors"
>
Kaufen
</button>
</div>
</div>
))}
</div>
</section>
)}
</div>
)}
{/* Edit Modals */}
<EditModal
isOpen={isEditDescriptionOpen}
title="Manifest bearbeiten"
initialValue={project.description}
multiline={true}
markdown={true}
onClose={() => setIsEditDescriptionOpen(false)}
onSave={async (newDescription) => {
try {
const response = await fetch(`https://vollidioten.ceraticsoft.de/api/projects/${project.id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ description: newDescription })
});
if (response.ok) {
// Update local data
dbService.updateProject(project.id, { description: newDescription });
console.log('Description updated successfully');
} else {
const errorData = await response.json();
alert(`Fehler beim Aktualisieren: ${errorData.error || 'Unbekannter Fehler'}`);
}
} catch (err) {
console.error('Error updating description:', err);
alert('Netzwerkfehler beim Aktualisieren der Beschreibung');
}
}}
/>
<EditModal
isOpen={isEditHiringOpen}
title={project.hiring ? 'Stellenanzeigen beenden' : 'Stellen ausschreiben'}
initialValue={project.hiring ? 'Ja, Stellen sind derzeit ausgeschrieben.' : 'Nein, derzeit keine offenen Stellen.'}
multiline={false}
onClose={() => setIsEditHiringOpen(false)}
onSave={async (value) => {
const newHiringStatus = !project.hiring;
try {
const response = await fetch(`https://vollidioten.ceraticsoft.de/api/projects/${project.id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ hiring: newHiringStatus })
});
if (response.ok) {
// Update local data
dbService.updateProject(project.id, { hiring: newHiringStatus });
console.log('Hiring status updated successfully:', newHiringStatus);
} else {
const errorData = await response.json();
alert(`Fehler beim Aktualisieren: ${errorData.error || 'Unbekannter Fehler'}`);
}
} catch (err) {
console.error('Error updating hiring status:', err);
alert('Netzwerkfehler beim Aktualisieren der Stellenanzeigen');
}
}}
/>
{/* Management Modals */}
<ShopManagementModal
isOpen={isShopModalOpen}
onClose={() => setIsShopModalOpen(false)}
projectId={project.id}
onUpdate={() => {
// Refresh project data
console.log('Shop updated, refreshing project data...');
// The dbService should automatically update via subscription
}}
/>
<EmployeeManagementModal
isOpen={isEmployeeModalOpen}
onClose={() => setIsEmployeeModalOpen(false)}
projectId={project.id}
onUpdate={() => {
// Refresh project data
console.log('Employees updated, refreshing project data...');
}}
/>
<BannerManagementModal
isOpen={isBannerModalOpen}
onClose={() => setIsBannerModalOpen(false)}
projectId={project.id}
currentBannerUrl={project.bannerUrl || ''}
onUpdate={() => {
// Refresh project data
console.log('Banner updated, refreshing project data...');
}}
/>
<LogoManagementModal
isOpen={isLogoModalOpen}
onClose={() => setIsLogoModalOpen(false)}
projectId={project.id}
currentLogoUrl={project.logoUrl || ''}
onUpdate={() => {
// Refresh project data
console.log('Logo updated, refreshing project data...');
}}
/>
<GalleryManagementModal
isOpen={isGalleryModalOpen}
onClose={() => setIsGalleryModalOpen(false)}
projectId={project.id}
onUpdate={() => {
// Refresh project data
console.log('Gallery updated, refreshing project data...');
}}
/>
<DeleteProjectModal
isOpen={isDeleteModalOpen}
onClose={() => setIsDeleteModalOpen(false)}
projectId={project.id}
projectTitle={project.title}
onDelete={async () => {
try {
const response = await fetch(`https://vollidioten.ceraticsoft.de/api/projects/${project.id}`, {
method: 'DELETE',
credentials: 'include'
});
if (response.ok) {
alert('Projekt erfolgreich gelöscht!');
onBack(); // Navigate back to projects list
} else {
alert('Fehler beim Löschen des Projekts');
}
} catch (err) {
console.error('Error deleting project:', err);
alert('Netzwerkfehler beim Löschen');
}
}}
/>
</div>
</div>
);
};
export default ProjectProfile;