dashboard.blade.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. <div class="dashboard-container">
  2. <style>
  3. .dashboard-container {
  4. background: #F6F7FF;
  5. min-height: 100vh;
  6. padding: 20px;
  7. font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  8. }
  9. .dashboard-grid {
  10. display: grid;
  11. grid-template-columns: 1fr 1fr 1fr;
  12. gap: 20px;
  13. margin-bottom: 20px;
  14. }
  15. .dashboard-section {
  16. background: white;
  17. border-radius: 12px;
  18. padding: 20px;
  19. box-shadow: 0 2px 10px rgba(0,0,0,0.05);
  20. }
  21. .stat-card {
  22. background: white;
  23. border-radius: 12px;
  24. padding: 20px;
  25. box-shadow: 0 2px 10px rgba(0,0,0,0.05);
  26. position: relative;
  27. }
  28. .stat-card-header {
  29. display: flex;
  30. justify-content: space-between;
  31. align-items: center;
  32. margin-bottom: 10px;
  33. }
  34. .stat-card-title {
  35. font-size: 14px;
  36. color: #666;
  37. font-weight: 500;
  38. }
  39. .stat-card-value {
  40. font-size: 48px;
  41. font-weight: bold;
  42. color: #333;
  43. margin: 10px 0;
  44. }
  45. .stat-card-change {
  46. font-size: 12px;
  47. color: #666;
  48. }
  49. .stat-card-change.positive {
  50. color: #339E8E;
  51. }
  52. .stat-card-change.negative {
  53. color: #D6234F;
  54. }
  55. .stat-icon {
  56. width: 24px;
  57. height: 24px;
  58. border-radius: 4px;
  59. display: flex;
  60. align-items: center;
  61. justify-content: center;
  62. color: white;
  63. font-size: 12px;
  64. }
  65. .courses-list {
  66. max-height: 300px;
  67. overflow-y: auto;
  68. }
  69. .course-item {
  70. padding: 12px;
  71. border-left: 4px solid #7438FA;
  72. margin-bottom: 8px;
  73. background: #F6F7FF;
  74. border-radius: 0 8px 8px 0;
  75. }
  76. .course-time {
  77. font-weight: bold;
  78. color: #333;
  79. font-size: 14px;
  80. }
  81. .course-name {
  82. font-size: 13px;
  83. color: #7438FA;
  84. font-weight: 600;
  85. }
  86. .course-days {
  87. font-size: 12px;
  88. color: #666;
  89. }
  90. .fields-grid {
  91. display: grid;
  92. grid-template-columns: 1fr 1fr;
  93. gap: 10px;
  94. }
  95. .field-item {
  96. padding: 12px;
  97. border: 2px solid #339E8E;
  98. border-radius: 8px;
  99. text-align: center;
  100. background: white;
  101. }
  102. .field-item.occupied {
  103. border-color: #D6234F;
  104. background: #FFF5F7;
  105. }
  106. .field-name {
  107. font-weight: bold;
  108. color: #333;
  109. }
  110. .field-time {
  111. color: #666;
  112. font-size: 12px;
  113. }
  114. .notes-section {
  115. background: #F6F7FF;
  116. border-radius: 8px;
  117. padding: 15px;
  118. margin-top: 15px;
  119. }
  120. .notes-input {
  121. width: 100%;
  122. border: none;
  123. background: transparent;
  124. outline: none;
  125. font-size: 14px;
  126. min-height: 60px;
  127. resize: vertical;
  128. }
  129. .save-btn {
  130. background: #7438FA;
  131. color: white;
  132. border: none;
  133. padding: 8px 16px;
  134. border-radius: 6px;
  135. font-size: 12px;
  136. cursor: pointer;
  137. margin-top: 10px;
  138. }
  139. .save-btn:hover {
  140. background: #6028E0;
  141. }
  142. .notes-list {
  143. max-height: 200px;
  144. overflow-y: auto;
  145. margin-bottom: 15px;
  146. }
  147. .note-item {
  148. display: flex;
  149. align-items: flex-start;
  150. gap: 10px;
  151. padding: 10px;
  152. background: white;
  153. border-radius: 8px;
  154. margin-bottom: 8px;
  155. border-left: 3px solid #7438FA;
  156. }
  157. .note-checkbox {
  158. width: 18px;
  159. height: 18px;
  160. border: 2px solid #7438FA;
  161. border-radius: 4px;
  162. background: white;
  163. cursor: pointer;
  164. display: flex;
  165. align-items: center;
  166. justify-content: center;
  167. color: white;
  168. font-size: 12px;
  169. font-weight: bold;
  170. transition: all 0.2s ease;
  171. flex-shrink: 0;
  172. margin-top: 2px;
  173. }
  174. .note-checkbox:hover {
  175. background: #7438FA;
  176. transform: scale(1.1);
  177. }
  178. .note-content {
  179. flex: 1;
  180. }
  181. .note-text {
  182. color: #333;
  183. font-size: 14px;
  184. line-height: 1.4;
  185. margin-bottom: 5px;
  186. }
  187. .note-date {
  188. color: #666;
  189. font-size: 11px;
  190. }
  191. .empty-notes {
  192. text-align: center;
  193. color: #666;
  194. font-size: 13px;
  195. padding: 20px;
  196. font-style: italic;
  197. }
  198. .chart-container {
  199. background: white;
  200. border-radius: 12px;
  201. padding: 20px;
  202. box-shadow: 0 2px 10px rgba(0,0,0,0.05);
  203. grid-column: span 3;
  204. }
  205. .financial-cards {
  206. display: grid;
  207. grid-template-columns: 1fr 1fr;
  208. gap: 20px;
  209. margin-bottom: 20px;
  210. }
  211. .financial-card {
  212. background: white;
  213. border-radius: 12px;
  214. padding: 20px;
  215. box-shadow: 0 2px 10px rgba(0,0,0,0.05);
  216. text-align: center;
  217. }
  218. .financial-card.income {
  219. border-left: 4px solid #339E8E;
  220. }
  221. .financial-card.expense {
  222. border-left: 4px solid #D6234F;
  223. }
  224. .financial-amount {
  225. font-size: 36px;
  226. font-weight: bold;
  227. margin: 10px 0;
  228. }
  229. .financial-amount.income {
  230. color: #339E8E;
  231. }
  232. .financial-amount.expense {
  233. color: #D6234F;
  234. }
  235. .recent-users-table {
  236. width: 100%;
  237. border-collapse: collapse;
  238. }
  239. .recent-users-table th,
  240. .recent-users-table td {
  241. text-align: left;
  242. padding: 12px 8px;
  243. border-bottom: 1px solid #f0f0f0;
  244. }
  245. .recent-users-table th {
  246. background: #F6F7FF;
  247. font-weight: 600;
  248. color: #333;
  249. font-size: 12px;
  250. }
  251. .recent-users-table td {
  252. font-size: 14px;
  253. color: #333;
  254. }
  255. .transaction-list {
  256. max-height: 300px;
  257. overflow-y: auto;
  258. }
  259. .transaction-item {
  260. display: flex;
  261. justify-content: space-between;
  262. align-items: center;
  263. padding: 12px;
  264. border-bottom: 1px solid #f0f0f0;
  265. }
  266. .transaction-name {
  267. font-weight: 500;
  268. color: #333;
  269. }
  270. .transaction-amount {
  271. font-weight: bold;
  272. }
  273. .transaction-type {
  274. font-size: 10px;
  275. padding: 4px 8px;
  276. border-radius: 12px;
  277. color: white;
  278. font-weight: bold;
  279. }
  280. .transaction-type.income {
  281. background: #339E8E;
  282. }
  283. .transaction-type.expense {
  284. background: #D6234F;
  285. }
  286. .participation-bar {
  287. height: 20px;
  288. background: #f0f0f0;
  289. border-radius: 10px;
  290. overflow: hidden;
  291. margin: 8px 0;
  292. }
  293. .participation-fill {
  294. height: 100%;
  295. transition: width 0.3s ease;
  296. }
  297. .participation-fill.padel {
  298. background: #FFD700;
  299. }
  300. .participation-fill.tennis {
  301. background: #8B4CF7;
  302. }
  303. .participation-fill.pallavolo {
  304. background: #FF6B35;
  305. }
  306. .participation-fill.yoga {
  307. background: #339E8E;
  308. }
  309. .section-title {
  310. font-size: 18px;
  311. font-weight: bold;
  312. color: #333;
  313. margin-bottom: 20px;
  314. }
  315. .chart-title {
  316. font-size: 16px;
  317. font-weight: 600;
  318. color: #333;
  319. margin-bottom: 15px;
  320. }
  321. .grid-4 {
  322. display: grid;
  323. grid-template-columns: repeat(4, 1fr);
  324. gap: 15px;
  325. margin-bottom: 20px;
  326. }
  327. .grid-3 {
  328. display: grid;
  329. grid-template-columns: repeat(3, 1fr);
  330. gap: 20px;
  331. margin-bottom: 20px;
  332. }
  333. .grid-2 {
  334. display: grid;
  335. grid-template-columns: repeat(2, 1fr);
  336. gap: 20px;
  337. margin-bottom: 20px;
  338. }
  339. .full-width {
  340. grid-column: span 3;
  341. }
  342. .half-width {
  343. grid-column: span 2;
  344. }
  345. .fade-out {
  346. opacity: 0;
  347. transform: translateX(100%);
  348. transition: all 0.3s ease;
  349. }
  350. </style>
  351. <!-- User Statistics Cards -->
  352. <div class="grid-4">
  353. <div class="stat-card">
  354. <div class="stat-card-header">
  355. <div class="stat-card-title">Utenti Totali</div>
  356. <div class="stat-icon">👥</div>
  357. </div>
  358. <div class="stat-card-value">{{$activeUsers}}</div>
  359. </div>
  360. <div class="stat-card">
  361. <div class="stat-card-header">
  362. <div class="stat-card-title">Tesserati</div>
  363. <div class="stat-icon">📋</div>
  364. </div>
  365. <div class="stat-card-value">{{$registeredUsers}}</div>
  366. </div>
  367. <div class="stat-card">
  368. <div class="stat-card-header">
  369. <div class="stat-card-title">Certificati medici scaduti</div>
  370. <div class="stat-icon">📄</div>
  371. </div>
  372. <div class="stat-card-value">{{$expiredCertificates}}</div>
  373. </div>
  374. <div class="stat-card">
  375. <div class="stat-card-header">
  376. <div class="stat-card-title">Abbonamenti sospesi</div>
  377. <div class="stat-icon">⏸️</div>
  378. </div>
  379. <div class="stat-card-value">{{$suspendedSubscriptions}}</div>
  380. </div>
  381. </div>
  382. <div class="grid-3">
  383. <div class="dashboard-section">
  384. <div class="section-title">Ultimi utenti registrati</div>
  385. @if(count($recentUsers) > 0)
  386. <table class="recent-users-table">
  387. <thead>
  388. <tr>
  389. <th>Cognome</th>
  390. <th>Nome</th>
  391. <th>Telefono</th>
  392. <th>Email</th>
  393. </tr>
  394. </thead>
  395. <tbody>
  396. @foreach($recentUsers as $user)
  397. <tr>
  398. <td>{{$user['surname']}}</td>
  399. <td>{{$user['name']}}</td>
  400. <td>{{$user['phone']}}</td>
  401. <td>{{$user['email']}}</td>
  402. </tr>
  403. @endforeach
  404. </tbody>
  405. </table>
  406. @else
  407. <div style="text-align: center; color: #666; padding: 40px;">
  408. Nessun utente registrato di recente
  409. </div>
  410. @endif
  411. </div>
  412. <!-- Corsi Section -->
  413. <div class="dashboard-section">
  414. <div class="section-title">
  415. Corsi
  416. </div>
  417. @if(count($courses) > 0)
  418. <div class="courses-list">
  419. @foreach($courses as $course)
  420. <div class="course-item">
  421. <div class="course-time">{{$course['time']}}</div>
  422. <div class="course-name">{{$course['full_name'] ?? $course['course_name']}}</div>
  423. <div class="course-days">{{$course['days']}}</div>
  424. @if(!empty($course['level_name']) || !empty($course['frequency_name']))
  425. <div style="font-size: 11px; color: #888; margin-top: 4px;">
  426. @if(!empty($course['level_name']))
  427. <span>{{$course['level_name']}}</span>
  428. @endif
  429. @if(!empty($course['level_name']) && !empty($course['frequency_name']))
  430. <span> • </span>
  431. @endif
  432. @if(!empty($course['frequency_name']))
  433. <span>{{$course['frequency_name']}}</span>
  434. @endif
  435. </div>
  436. @endif
  437. </div>
  438. @endforeach
  439. </div>
  440. @else
  441. <div style="text-align: center; color: #666; padding: 40px;">
  442. Nessun corso programmato per oggi
  443. <div style="font-size: 12px; margin-top: 10px; color: #999;">
  444. Oggi è: <strong>{{$dayName ?? 'N/A'}}</strong>
  445. </div>
  446. </div>
  447. @endif
  448. </div>
  449. <!-- To Do Section -->
  450. <div class="dashboard-section">
  451. <div class="section-title">To do</div>
  452. <div style="font-size: 14px; color: #666; margin-bottom: 10px;">{{date('d/m/Y')}}</div>
  453. <!-- Notes List -->
  454. @if(count($savedNotes) > 0)
  455. <div class="notes-list">
  456. @foreach($savedNotes as $note)
  457. <div class="note-item">
  458. <div class="note-checkbox" wire:click="completeNote('{{$note['id']}}')" title="Segna come completato">
  459. </div>
  460. <div class="note-content">
  461. <div class="note-text">{{$note['text']}}</div>
  462. <div class="note-date">{{$note['created_at']}}</div>
  463. </div>
  464. </div>
  465. @endforeach
  466. </div>
  467. @else
  468. <div class="empty-notes">
  469. Nessuna nota salvata
  470. </div>
  471. @endif
  472. <!-- Add Note Section -->
  473. <div class="notes-section">
  474. <textarea class="notes-input" placeholder="Inserisci una nuova nota..." wire:model="notes"></textarea>
  475. <button class="save-btn" wire:click="saveNote">SALVA</button>
  476. </div>
  477. </div>
  478. </div>
  479. <div class="grid-2">
  480. <!-- Courses Participation Section -->
  481. <div class="dashboard-section">
  482. <div class="section-title">Corsi con più partecipazioni</div>
  483. @if(count($coursesParticipation) > 0)
  484. <div style="padding: 10px 0;">
  485. @foreach($coursesParticipation as $course)
  486. <div style="margin-bottom: 20px;">
  487. <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 5px;">
  488. <span style="font-weight: 600; color: #333; font-size: 14px;">{{$course['course_name']}}</span>
  489. <span style="font-size: 12px; color: #666;">{{$course['participants']}} partecipanti</span>
  490. </div>
  491. <div class="participation-bar">
  492. <div class="participation-fill {{$course['color']}}" style="width: {{$course['percentage']}}%"></div>
  493. </div>
  494. </div>
  495. @endforeach
  496. </div>
  497. @else
  498. <div style="text-align: center; color: #666; padding: 40px;">
  499. Nessun corso con partecipazioni
  500. </div>
  501. @endif
  502. </div>
  503. <!-- Financial Cards moved here -->
  504. <div>
  505. <div class="financial-cards" style="margin-bottom: 0;">
  506. <div class="financial-card income">
  507. <div style="font-size: 14px; color: #666; margin-bottom: 10px;">Incassato mese corrente</div>
  508. <div class="financial-amount income">€ {{number_format($toReceive, 2)}}</div>
  509. </div>
  510. <div class="financial-card expense">
  511. <div style="font-size: 14px; color: #666; margin-bottom: 10px;">Pagato mese corrente</div>
  512. <div class="financial-amount expense">€ {{number_format($toPay, 2)}}</div>
  513. </div>
  514. </div>
  515. </div>
  516. </div>
  517. <div class="dashboard-section">
  518. <div class="section-title">Ultimi movimenti finanziari</div>
  519. @if(count($recentTransactions) > 0)
  520. <div class="transaction-list">
  521. @foreach($recentTransactions as $transaction)
  522. <div class="transaction-item">
  523. <div class="transaction-name">{{$transaction['name']}}</div>
  524. <div style="display: flex; align-items: center; gap: 10px;">
  525. <div class="transaction-amount">€ {{number_format($transaction['amount'], 2)}}</div>
  526. <div class="transaction-type {{$transaction['type'] == 'ENTRATA' ? 'income' : 'expense'}}">
  527. {{$transaction['type']}}
  528. </div>
  529. </div>
  530. </div>
  531. @endforeach
  532. </div>
  533. @else
  534. <div style="text-align: center; color: #666; padding: 40px;">
  535. Nessun movimento finanziario recente
  536. </div>
  537. @endif
  538. </div>
  539. </div>
  540. @push('scripts')
  541. <script>
  542. window.addEventListener('note-saved', event => {
  543. // Show success message
  544. if (typeof toastr !== 'undefined') {
  545. toastr.success('Nota salvata con successo!');
  546. } else {
  547. alert('Nota salvata con successo!');
  548. }
  549. });
  550. window.addEventListener('courses-activated', event => {
  551. if (typeof toastr !== 'undefined') {
  552. toastr.success(event.detail.message);
  553. } else {
  554. alert(event.detail.message);
  555. }
  556. });
  557. window.addEventListener('debug-completed', event => {
  558. if (typeof toastr !== 'undefined') {
  559. toastr.info('Debug completato - controlla i log');
  560. } else {
  561. alert('Debug completato - controlla i log');
  562. }
  563. });
  564. // Optional: Add keyboard shortcut to save note
  565. document.addEventListener('keydown', function(e) {
  566. if (e.ctrlKey && e.key === 'Enter') {
  567. let textarea = document.querySelector('.notes-input');
  568. if (textarea === document.activeElement) {
  569. Livewire.emit('saveNote');
  570. }
  571. }
  572. });
  573. </script>
  574. @endpush