dashboard.blade.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  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. <div class="grid-4">
  352. <div class="stat-card">
  353. <div class="stat-card-header">
  354. <div class="stat-card-title">Utenti Totali</div>
  355. <div class="stat-icon">👥</div>
  356. </div>
  357. <div class="stat-card-value">{{$activeUsers}}</div>
  358. </div>
  359. <div class="stat-card">
  360. <div class="stat-card-header">
  361. <div class="stat-card-title">Tesserati</div>
  362. <div class="stat-icon">📋</div>
  363. </div>
  364. <div class="stat-card-value">{{$registeredUsers}}</div>
  365. </div>
  366. <div class="stat-card">
  367. <div class="stat-card-header">
  368. <div class="stat-card-title">Certificati medici scaduti</div>
  369. <div class="stat-icon">📄</div>
  370. </div>
  371. <div class="stat-card-value">{{$expiredCertificates}}</div>
  372. </div>
  373. <div class="stat-card">
  374. <div class="stat-card-header">
  375. <div class="stat-card-title">Abbonamenti sospesi</div>
  376. <div class="stat-icon">⏸️</div>
  377. </div>
  378. <div class="stat-card-value">{{$suspendedSubscriptions}}</div>
  379. </div>
  380. </div>
  381. <div class="grid-3">
  382. <div class="dashboard-section">
  383. <div class="section-title">Ultimi utenti registrati</div>
  384. @if(count($recentUsers) > 0)
  385. <table class="recent-users-table">
  386. <thead>
  387. <tr>
  388. <th>Cognome</th>
  389. <th>Nome</th>
  390. <th>Telefono</th>
  391. <th>Email</th>
  392. </tr>
  393. </thead>
  394. <tbody>
  395. @foreach($recentUsers as $user)
  396. <tr>
  397. <td>{{$user['surname']}}</td>
  398. <td>{{$user['name']}}</td>
  399. <td>{{$user['phone']}}</td>
  400. <td>{{$user['email']}}</td>
  401. </tr>
  402. @endforeach
  403. </tbody>
  404. </table>
  405. @else
  406. <div style="text-align: center; color: #666; padding: 40px;">
  407. Nessun utente registrato di recente
  408. </div>
  409. @endif
  410. </div>
  411. <div class="dashboard-section">
  412. <div class="section-title">Corsi</div>
  413. @if(count($courses) > 0)
  414. <div class="courses-list">
  415. @foreach($courses as $course)
  416. <div class="course-item">
  417. <div class="course-time">{{$course['time']}}</div>
  418. <div class="course-name">{{$course['course_name']}}</div>
  419. <div class="course-days">{{$course['days']}}</div>
  420. </div>
  421. @endforeach
  422. </div>
  423. @else
  424. <div style="text-align: center; color: #666; padding: 40px;">
  425. Nessun corso programmato per oggi
  426. </div>
  427. @endif
  428. </div>
  429. <div class="dashboard-section">
  430. <div class="section-title">To do</div>
  431. <div style="font-size: 14px; color: #666; margin-bottom: 10px;">{{date('d/m/Y')}}</div>
  432. @if(count($savedNotes) > 0)
  433. <div class="notes-list">
  434. @foreach($savedNotes as $note)
  435. <div class="note-item">
  436. <div class="note-checkbox" wire:click="completeNote('{{$note['id']}}')" title="Segna come completato">
  437. </div>
  438. <div class="note-content">
  439. <div class="note-text">{{$note['text']}}</div>
  440. <div class="note-date">{{$note['created_at']}}</div>
  441. </div>
  442. </div>
  443. @endforeach
  444. </div>
  445. @else
  446. <div class="empty-notes">
  447. Nessuna nota salvata
  448. </div>
  449. @endif
  450. <div class="notes-section">
  451. <textarea class="notes-input" placeholder="Inserisci una nuova nota..." wire:model="notes"></textarea>
  452. <button class="save-btn" wire:click="saveNote">SALVA</button>
  453. </div>
  454. </div>
  455. </div>
  456. <div class="grid-2">
  457. <div class="dashboard-section">
  458. <div class="section-title">Corsi con più partecipazioni</div>
  459. @if(count($coursesParticipation) > 0)
  460. <div style="padding: 10px 0;">
  461. @foreach($coursesParticipation as $course)
  462. <div style="margin-bottom: 20px;">
  463. <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 5px;">
  464. <span style="font-weight: 600; color: #333; font-size: 14px;">{{$course['course_name']}}</span>
  465. <span style="font-size: 12px; color: #666;">{{$course['participants']}} partecipanti</span>
  466. </div>
  467. <div class="participation-bar">
  468. <div class="participation-fill {{$course['color']}}" style="width: {{$course['percentage']}}%"></div>
  469. </div>
  470. </div>
  471. @endforeach
  472. </div>
  473. @else
  474. <div style="text-align: center; color: #666; padding: 40px;">
  475. Nessun corso con partecipazioni
  476. </div>
  477. @endif
  478. </div>
  479. <div>
  480. <div class="financial-cards" style="margin-bottom: 0;">
  481. <div class="financial-card income">
  482. <div style="font-size: 14px; color: #666; margin-bottom: 10px;">Incassato mese corrente</div>
  483. <div class="financial-amount income">€ {{number_format($toReceive, 2)}}</div>
  484. </div>
  485. <div class="financial-card expense">
  486. <div style="font-size: 14px; color: #666; margin-bottom: 10px;">Pagato mese corrente</div>
  487. <div class="financial-amount expense">€ {{number_format($toPay, 2)}}</div>
  488. </div>
  489. </div>
  490. </div>
  491. </div>
  492. <div class="dashboard-section">
  493. <div class="section-title">Ultimi movimenti finanziari</div>
  494. @if(count($recentTransactions) > 0)
  495. <div class="transaction-list">
  496. @foreach($recentTransactions as $transaction)
  497. <div class="transaction-item">
  498. <div class="transaction-name">{{$transaction['name']}}</div>
  499. <div style="display: flex; align-items: center; gap: 10px;">
  500. <div class="transaction-amount">€ {{number_format($transaction['amount'], 2)}}</div>
  501. <div class="transaction-type {{$transaction['type'] == 'ENTRATA' ? 'income' : 'expense'}}">
  502. {{$transaction['type']}}
  503. </div>
  504. </div>
  505. </div>
  506. @endforeach
  507. </div>
  508. @else
  509. <div style="text-align: center; color: #666; padding: 40px;">
  510. Nessun movimento finanziario recente
  511. </div>
  512. @endif
  513. </div>
  514. </div>
  515. @push('scripts')
  516. <script>
  517. window.addEventListener('note-saved', event => {
  518. // Show success message
  519. if (typeof toastr !== 'undefined') {
  520. toastr.success('Nota salvata con successo!');
  521. } else {
  522. alert('Nota salvata con successo!');
  523. }
  524. });
  525. window.addEventListener('note-completed', event => {
  526. if (typeof toastr !== 'undefined') {
  527. toastr.success('Nota completata!');
  528. } else {
  529. alert('Nota completata!');
  530. }
  531. });
  532. document.addEventListener('keydown', function(e) {
  533. if (e.ctrlKey && e.key === 'Enter') {
  534. let textarea = document.querySelector('.notes-input');
  535. if (textarea === document.activeElement) {
  536. Livewire.emit('saveNote');
  537. }
  538. }
  539. });
  540. </script>
  541. @endpush