// ============================================================================
// DASHBOARD VIEW
// ============================================================================
const DashboardView = () => {
const { customer } = useAuth();
const [screens, setScreens] = useState([]);
const [loading, setLoading] = useState(true);
const [stats, setStats] = useState({
total_screens: 0,
active_screens: 0,
total_ads: 0,
total_news: 0
});
useEffect(() => {
loadScreens();
}, []);
const loadScreens = async () => {
setLoading(true);
try {
const result = await api.getScreens(customer.id);
if (result.screens) {
setScreens(result.screens);
// Calculer les stats
setStats({
total_screens: result.screens.length,
active_screens: result.screens.filter(s => s.is_active == 1).length,
total_ads: result.screens.reduce((sum, s) => sum + (parseInt(s.ads_count) || 0), 0),
total_news: result.screens.reduce((sum, s) => sum + (parseInt(s.news_count) || 0), 0)
});
}
} catch (error) {
console.error('Erreur chargement écrans:', error);
}
setLoading(false);
};
if (loading) return ;
return (
Dashboard
{/* Stats Cards */}
Écrans totaux
{stats.total_screens}
Écrans actifs
{stats.active_screens}
Publicités
{stats.total_ads}
Alertes actives
{stats.total_news}
{/* Liste des écrans */}
{screens.length === 0 ? (
) : (
{screens.map(screen => (
{screen.label}
{screen.location_city} • {screen.address}
{screen.is_active == 1 ? 'Actif' : 'Inactif'}
{screen.ads_count || 0} pub(s)
{screen.news_count || 0} alerte(s)
))}
)}
);
};
// ============================================================================
// SCREENS VIEW
// ============================================================================
const ScreensView = () => {
const { customer } = useAuth();
const toast = useToast();
const [screens, setScreens] = useState([]);
const [configurations, setConfigurations] = useState([]);
const [loading, setLoading] = useState(true);
const [isModalOpen, setIsModalOpen] = useState(false);
const [isDetailModalOpen, setIsDetailModalOpen] = useState(false);
const [isPreviewModalOpen, setIsPreviewModalOpen] = useState(false);
const [editingScreen, setEditingScreen] = useState(null);
const [viewingScreen, setViewingScreen] = useState(null);
const [previewUrl, setPreviewUrl] = useState('');
// Fermer la modal de preview avec la touche Échap
useEffect(() => {
const handleEscape = (e) => {
if (e.key === 'Escape' && isPreviewModalOpen) {
setIsPreviewModalOpen(false);
}
};
window.addEventListener('keydown', handleEscape);
return () => window.removeEventListener('keydown', handleEscape);
}, [isPreviewModalOpen]);
// Form state
const [formLabel, setFormLabel] = useState('');
const [formCity, setFormCity] = useState('Genève');
const [formAddress, setFormAddress] = useState('');
const [formLatitude, setFormLatitude] = useState(null);
const [formLongitude, setFormLongitude] = useState(null);
const [formBusStop, setFormBusStop] = useState('');
const [formBusCode, setFormBusCode] = useState('');
const [formActive, setFormActive] = useState(true);
const [formConfigurationId, setFormConfigurationId] = useState(null);
const [formConciergeId, setFormConciergeId] = useState(null);
// Liste des concierges
const [concierges, setConcierges] = useState([]);
useEffect(() => {
loadScreens();
loadConfigurations();
loadConcierges();
}, []);
const loadScreens = async () => {
setLoading(true);
try {
const result = await api.getScreens(customer.id);
if (result.screens) {
setScreens(result.screens);
}
} catch (error) {
toast.error('Erreur lors du chargement');
}
setLoading(false);
};
const loadConfigurations = async () => {
try {
const result = await api.getConfigurations(customer.id);
if (result.configurations) {
setConfigurations(result.configurations);
}
} catch (error) {
console.error('Erreur lors du chargement des configurations');
}
};
const loadConcierges = async () => {
try {
const result = await api.getConcierges(customer.id);
if (result.concierges) {
setConcierges(result.concierges);
}
} catch (error) {
console.error('Erreur lors du chargement des concierges');
}
};
const openModal = (screen = null) => {
if (screen) {
setEditingScreen(screen);
setFormLabel(screen.label);
setFormCity(screen.location_city);
setFormAddress(screen.address);
setFormLatitude(screen.latitude || null);
setFormLongitude(screen.longitude || null);
setFormBusStop(screen.bus_stop_name || '');
setFormBusCode(screen.bus_stop_code || '');
setFormActive(screen.is_active == 1);
setFormConfigurationId(screen.configuration_id ? parseInt(screen.configuration_id) : null);
setFormConciergeId(screen.concierge_id ? parseInt(screen.concierge_id) : null);
} else {
setEditingScreen(null);
setFormLabel('');
setFormCity('Genève');
setFormAddress('');
setFormLatitude(null);
setFormLongitude(null);
setFormBusStop('');
setFormBusCode('');
setFormActive(true);
setFormConfigurationId(configurations.length > 0 ? configurations[0].id : null);
setFormConciergeId(null);
}
setIsModalOpen(true);
};
const handleSubmit = async (e) => {
e.preventDefault();
const data = {
customer_id: customer.id,
label: formLabel,
location_city: formCity,
address: formAddress,
latitude: formLatitude,
longitude: formLongitude,
bus_stop_name: formBusStop,
bus_stop_code: formBusCode,
is_active: formActive ? 1 : 0,
configuration_id: formConfigurationId,
concierge_id: formConciergeId
};
try {
if (editingScreen) {
data.screen_id = editingScreen.id;
const result = await api.updateScreen(data);
if (result.success) {
toast.success('Écran modifié avec succès');
}
} else {
const result = await api.createScreen(data);
if (result.success) {
toast.success('Écran créé avec succès');
toast.info(`Code écran : ${result.screen_code}`);
}
}
loadScreens();
setIsModalOpen(false);
} catch (error) {
toast.error('Erreur lors de l\'enregistrement');
}
};
const openDetailModal = (screen) => {
setViewingScreen(screen);
setIsDetailModalOpen(true);
};
const closeDetailModal = () => {
setIsDetailModalOpen(false);
setViewingScreen(null);
};
const handleDelete = async (screenId) => {
if (!confirm('Êtes-vous sûr de vouloir supprimer cet écran ?')) return;
try {
const result = await api.deleteScreen(screenId);
if (result.success) {
toast.success('Écran supprimé');
loadScreens();
}
} catch (error) {
toast.error('Erreur lors de la suppression');
}
};
const handlePreview = (screen) => {
// Détecter si on est en local ou en production
const isLocal = window.location.hostname === 'localhost' ||
window.location.hostname === '127.0.0.1' ||
window.location.hostname.includes('local');
// Construire l'URL de base (HTTPS partout car le serveur local utilise SSL)
const baseUrl = isLocal
? 'https://local.smarthall.screen:8890'
: 'https://screen.smarthall.ch';
// Utiliser md5_id ou screen_code en fallback
const identifier = screen.md5_id || screen.screen_code;
// Construire l'URL complète
const url = `${baseUrl}/?md5=${identifier}`;
// Ouvrir dans une modal avec iframe
setPreviewUrl(url);
setIsPreviewModalOpen(true);
toast.info(`Chargement de la prévisualisation...`);
};
if (loading) return ;
return (
Mes Écrans
{screens.length === 0 ? (
openModal()}
icon="fa-plus"
>
Créer un écran
}
/>
) : (
{/* En-tête du tableau */}
Écran
Localisation
Configuration
Statistiques
Statut
Actions
{/* Lignes du tableau */}
{screens.map(screen => (
{/* Nom de l'écran */}
{screen.label}
{screen.screen_code}
{screen.md5_id && (
<>
•
{screen.md5_id.substring(0, 8)}...
>
)}
{/* Localisation */}
{screen.location_city}
{screen.address}
{/* Configuration */}
{screen.configuration_name ? (
{screen.configuration_name}
) : (
Aucune
)}
{/* Statistiques */}
{screen.ads_count || 0}
{screen.news_count || 0}
{/* Statut */}
{screen.is_active == 1 ? 'Actif' : 'Inactif'}
{/* Actions */}
))}
)}
{/* Modal Créer/Modifier */}
setIsModalOpen(false)}
title={editingScreen ? 'Modifier l\'écran' : 'Nouvel écran'}
>
{/* Modal de détail simplifiée */}
{viewingScreen && (
{/* Nom de l'écran */}
{viewingScreen.label}
{/* Météo */}
{viewingScreen.location_city || 'Non définie'}
{/* Adresse complète */}
{viewingScreen.address || 'Non définie'}
{(viewingScreen.latitude && viewingScreen.longitude) && (
Coordonnées GPS: {viewingScreen.latitude}, {viewingScreen.longitude}
)}
{/* Arrêt de bus */}
{viewingScreen.bus_stop_name || 'Non défini'}
{viewingScreen.bus_stop_code && (
Code: {viewingScreen.bus_stop_code}
)}
{/* Configuration */}
{viewingScreen.configuration_id ? (
configurations.find(c => c.id == viewingScreen.configuration_id)?.name || 'Configuration inconnue'
) : (
Aucune configuration (manuel)
)}
{/* Concierge */}
{viewingScreen.concierge_id ? (
concierges.find(c => c.id == viewingScreen.concierge_id)?.name || 'Concierge inconnu'
) : (
Aucun concierge
)}
{viewingScreen.concierge_id && concierges.find(c => c.id == viewingScreen.concierge_id)?.phone && (
Tél: {concierges.find(c => c.id == viewingScreen.concierge_id)?.phone}
)}
{/* Statut */}
{viewingScreen.is_active == 1 ? 'Actif' : 'Inactif'}
{/* Informations techniques */}
ID:
{viewingScreen.id}
Code:
{viewingScreen.screen_code}
API Key:
{viewingScreen.api_key}
)}
{/* Modal de Prévisualisation Écran - Plein écran avec Screenshot */}
{isPreviewModalOpen && (
setIsPreviewModalOpen(false)}
/>
)}
);
};
// Suite dans views.jsx pour les autres vues...