records_old.blade.php 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229
  1. <div class="col card--ui" id="card--dashboard">
  2. <header id="title--section" style="display:none !important" class="d-flex align-items-center justify-content-between">
  3. <div class="title--section_name d-flex align-items-center justify-content-between">
  4. <i class="ico--ui title_section utenti me-2"></i>
  5. <h2 class="primary">Prima nota</h2>
  6. </div>
  7. </header>
  8. <section id="subheader" class="">
  9. <div class="row g-3">
  10. <div class="col-md-3">
  11. Utente
  12. <select name="search_member_id" class="form-select filterMember" wire:model="filterMember">
  13. <option value="">--Seleziona--
  14. @foreach($members as $member)
  15. <option value="{{$member->id}}">{{$member->last_name}} {{$member->first_name}}
  16. @endforeach
  17. </select>
  18. </div>
  19. <div class="col-md-3">
  20. Causale
  21. <select name="search_causal_id[]" class="form-select filterCausals me-2" multiple="multiple" wire:model="filterCausals">
  22. @foreach($causals as $causal)
  23. <option value="{{$causal["id"]}}">{!!$causal["name"]!!}
  24. @endforeach
  25. </select>
  26. </div>
  27. <div class="col-md-3">
  28. Periodo
  29. <select wire:model="selectedPeriod" class="form-select" @if($isFiltering) disabled @endif style="height: 43px!important;">
  30. <option value="OGGI">Oggi</option>
  31. <option value="IERI">Ieri</option>
  32. <option value="MESE CORRENTE">Mese Corrente</option>
  33. <option value="MESE PRECEDENTE">Mese Precedente</option>
  34. <option value="ULTIMO TRIMESTRE">Ultimo Trimestre</option>
  35. <option value="ULTIMO QUADRIMESTRE">Ultimo Quadrimestre</option>
  36. </select>
  37. </div>
  38. <div class="col-md-3">
  39. <div class="prima--nota_buttons ms-auto" style="float:right; margin-top:25px;">
  40. <button class="btn--ui primary" wire:click="applyFilters" style="margin-right:5px;" @if($isFiltering) disabled @endif>
  41. @if($isFiltering)
  42. <i class="fas fa-spinner fa-spin"></i> CARICAMENTO...
  43. @else
  44. FILTRA
  45. @endif
  46. </button>
  47. <button class="btn--ui lightGrey reset reset" style="margin-left:5px;color:#10172A;" wire:click="resetFilters" @if($isFiltering) disabled @endif>RESET</button>
  48. </div>
  49. </div>
  50. </div>
  51. <div style="float:left; margin-top:10px; margin-bottom:10px;">
  52. {{-- <div class="dropdown">
  53. <button class="btn--ui_outline light dropdown-toggle" type="button" id="exportDropdown" data-bs-toggle="dropdown" aria-expanded="false"
  54. style="color:#10172A;" @if($isFiltering) disabled @endif>
  55. ESPORTA
  56. </button>
  57. <ul class="dropdown-menu" aria-labelledby="exportDropdown">
  58. <li><a class="dropdown-item" href="#" wire:click="openExportModal">Excel</a></li>
  59. <li><a class="dropdown-item" href="#" id="print">Stampa</a></li>
  60. </ul>
  61. </div> --}}
  62. <div class="dt-buttons btn-group flex-wrap">
  63. <button class="btn btn-secondary buttons-excel buttons-html5" tabindex="0" type="button" wire:click="openExportModal">
  64. <span><i class="fa-solid fa-file-excel"></i></span>
  65. </button>
  66. {{-- <button class="btn btn-secondary buttons-excel buttons-html5" tabindex="0" type="button" wire:click="openExportModal" style="border-top-right-radius: 0 !important;border-bottom-right-radius: 0 !important;">
  67. <span><i class="fa-solid fa-file-excel"></i></span>
  68. </button> --}}
  69. {{-- <button class="btn btn-secondary buttons-print" tabindex="0" type="button" id="print" style="border-top-left-radius: 0 !important;border-bottom-left-radius: 0 !important;">
  70. <span><i class="fa-solid fa-print"></i></span>
  71. </button> --}}
  72. </div>
  73. </div>
  74. </section>
  75. <section id="resume-table" class="scrollTable records-table" style="position: relative;">
  76. @if($isFiltering)
  77. <div class="loading-overlay">
  78. <div class="loading-content">
  79. <i class="fas fa-spinner fa-spin fa-3x"></i>
  80. <p>Caricamento dati in corso...</p>
  81. </div>
  82. </div>
  83. @endif
  84. <table class="table tablesaw tableHead tablesaw-stack" id="tablesaw-350" width="100%">
  85. <thead>
  86. <tr>
  87. <th scope="col">Data</th>
  88. <th scope="col" style="border-left:3px solid white;">Causale</th>
  89. <th scope="col" style="border-left:3px solid white;">Dettaglio Causale</th>
  90. <th scope="col" style="border-left:3px solid white;">Stato</th>
  91. <th scope="col" style="border-left:3px solid white;">Nominativo</th>
  92. @foreach($payments as $p)
  93. <th colspan="2" scope="col" style="text-align:center; border-left:3px solid white;">{{$p->name}}</th>
  94. @endforeach
  95. </tr>
  96. <tr>
  97. <th scope="col"></th>
  98. <th scope="col" style="border-left:3px solid white;"></th>
  99. <th scope="col" style="border-left:3px solid white;"></th>
  100. <th scope="col" style="border-left:3px solid white;"></th>
  101. <th scope="col" style="border-left:3px solid white;"></th>
  102. @foreach($payments as $p)
  103. @if($p->type == 'ALL')
  104. <th scope="col" style="text-align:center; border-left:3px solid white;">Entrate</th>
  105. <th scope="col" style="text-align:center">Uscite</th>
  106. @elseif($p->type == 'IN')
  107. <th scope="col" style="text-align:center; border-left:3px solid white;">Entrate</th>
  108. <th scope="col" style="text-align:center;"></th>
  109. @elseif($p->type == 'OUT')
  110. <th style="border-left:3px solid white;"></th>
  111. <th scope="col" style="text-align:center;">Uscite</th>
  112. @endif
  113. @endforeach
  114. </tr>
  115. </thead>
  116. <tbody id="checkall-target">
  117. @php $count = 0; @endphp
  118. @foreach($records as $causal => $record)
  119. <tr>
  120. @php
  121. $parts = explode("§", $causal);
  122. $d = $parts[0] ?? '';
  123. $c = $parts[1] ?? '';
  124. $n = $parts[2] ?? '';
  125. $det = $parts[3] ?? '';
  126. $del = $parts[4] ?? '';
  127. $detailParts = explode('|', $det);
  128. $isMultiple = count($detailParts) > 1;
  129. $displayDetail = $isMultiple ? 'Varie' : $det;
  130. @endphp
  131. <td style="background-color:{{$count % 2 == 0 ? 'white' : '#f2f4f7'}}">{{date("d/m/Y", strtotime($d))}}</td>
  132. <td style="border-left:3px solid white !important;background-color:{{$count % 2 == 0 ? 'white' : '#f2f4f7'}}">{{$c}}</td>
  133. <td style="border-left:3px solid white !important;background-color:{{$count % 2 == 0 ? 'white' : '#f2f4f7'}}">
  134. @if($isMultiple)
  135. <span class="varie-link" data-causals="{{implode('|', array_slice($detailParts, 1))}}" style="color: var(--color-blu); cursor: pointer; text-decoration: underline;">
  136. {{$displayDetail}}
  137. </span>
  138. @else
  139. {{$displayDetail}}
  140. @endif
  141. </td>
  142. <td style="border-left:3px solid white !important;background-color:{{$count % 2 == 0 ? 'white' : '#f2f4f7'}}">
  143. @if($del == 'DELETED')
  144. <span style='color:red'>Annullata</span>
  145. @endif
  146. </td>
  147. <td style="border-left:3px solid white !important;background-color:{{$count % 2 == 0 ? 'white' : '#f2f4f7'}}">{{$n}}</td>
  148. @foreach($payments as $p)
  149. @if(isset($record[$p->name]))
  150. <td style="text-align:right; border-left:3px solid white !important;background-color:{{$count % 2 == 0 ? 'white' : '#f2f4f7'}}">
  151. @if(isset($record[$p->name]["IN"]))
  152. <span class="tablesaw-cell-content " style="color:green">{{formatPrice($record[$p->name]["IN"])}}</span>
  153. @endif
  154. </td>
  155. <td style="text-align:right;background-color:{{$count % 2 == 0 ? 'white' : '#f2f4f7'}}">
  156. @if(isset($record[$p->name]["OUT"]))
  157. <span class="tablesaw-cell-content " style="color:red">{{formatPrice($record[$p->name]["OUT"])}}</span>
  158. @endif
  159. </td>
  160. @else
  161. <td style="border-left:3px solid white !important;background-color:{{$count % 2 == 0 ? 'white' : '#f2f4f7'}}"></td>
  162. <td style="background-color:{{$count % 2 == 0 ? 'white' : '#f2f4f7'}}"></td>
  163. @endif
  164. @endforeach
  165. </tr>
  166. @php $count++; @endphp
  167. @endforeach
  168. </tbody>
  169. <tfoot>
  170. <tr>
  171. <td></td>
  172. <td></td>
  173. <td></td>
  174. <td></td>
  175. <td><b>Totale</b></td>
  176. @foreach($payments as $p)
  177. @if(isset($totals[$p->name]))
  178. @if($p->type == 'ALL')
  179. <td style="text-align:right"><span class="tablesaw-cell-content primary" style="color:green; font-size:18px;"><b>{{formatPrice(isset($totals[$p->name]) ? $totals[$p->name]["IN"] : 0)}}</b></span></td>
  180. <td style="text-align:right"><span class="tablesaw-cell-content primary" style="color:red; font-size:18px;"><b>{{formatPrice(isset($totals[$p->name]) ? $totals[$p->name]["OUT"] : 0)}}</b></span></td>
  181. @elseif($p->type == 'IN')
  182. <td style="text-align:right"><span class="tablesaw-cell-content primary" style="color:green; font-size:18px;"><b>{{formatPrice(isset($totals[$p->name]) ? $totals[$p->name]["IN"] : 0)}}</b></span></td>
  183. <td style="text-align:right"><span class="tablesaw-cell-content primary" style="color:red; font-size:18px;"><b>&nbsp;</b></span></td>
  184. @elseif($p->type == 'OUT')
  185. <td style="text-align:right"><span class="tablesaw-cell-content primary" style="color:green; font-size:18px;"><b>&nbsp;</b></span></td>
  186. <td style="text-align:right"><span class="tablesaw-cell-content primary" style="color:red; font-size:18px;"><b>{{formatPrice(isset($totals[$p->name]) ? $totals[$p->name]["OUT"] : 0)}}</b></span></td>
  187. @endif
  188. @else
  189. @if($p->type == 'ALL')
  190. <td style="text-align:right"><span class="tablesaw-cell-content primary" style="color:green; font-size:18px;"><b>{{formatPrice(isset($totals[$p->name]) ? $totals[$p->name]["IN"] : 0)}}</b></span></td>
  191. <td style="text-align:right"><span class="tablesaw-cell-content primary" style="color:red; font-size:18px;"><b>{{formatPrice(isset($totals[$p->name]) ? $totals[$p->name]["OUT"] : 0)}}</b></span></td>
  192. @elseif($p->type == 'IN')
  193. <td style="text-align:right"><span class="tablesaw-cell-content primary" style="color:green; font-size:18px;"><b>{{formatPrice(isset($totals[$p->name]) ? $totals[$p->name]["IN"] : 0)}}</b></span></td>
  194. <td style="text-align:center"><span class="tablesaw-cell-content primary" style="color:red; font-size:18px;"><b>&nbsp;</b></span></td>
  195. @elseif($p->type == 'OUT')
  196. <td style="text-align:right"><span class="tablesaw-cell-content primary" style="color:green; font-size:18px;"><b>&nbsp;</b></span></td>
  197. <td style="text-align:center"><span class="tablesaw-cell-content primary" style="color:red; font-size:18px;"><b>{{formatPrice(isset($totals[$p->name]) ? $totals[$p->name]["OUT"] : 0)}}</b></span></td>
  198. @endif
  199. @endif
  200. @endforeach
  201. </tr>
  202. <tr style="display:none">
  203. <td></td>
  204. <td><b>Differenza</b></td>
  205. @foreach($payments as $p)
  206. @if(isset($totals[$p->name]))
  207. @php
  208. $diff = $totals[$p->name]["IN"] - $totals[$p->name]["OUT"];
  209. @endphp
  210. @if($diff < 0)
  211. <td></td>
  212. @endif
  213. <td style="text-align:right"><span class="tablesaw-cell-content primary" style="color:{{$diff > 0 ? 'green' : 'red'}}; font-size:18px;"><b>{{formatPrice($diff)}}</b></span></td>
  214. @if($diff > 0)
  215. <td></td>
  216. @endif
  217. @else
  218. <td colspan="2" style="text-align:right"><b>{{formatPrice(0)}}</b></td>
  219. @endif
  220. @endforeach
  221. </tr>
  222. </tfoot>
  223. </table>
  224. <button type="button" class="btn btn-floating btn-lg" id="btn-back-to-bottom"><i class="fas fa-arrow-down"></i></button>
  225. <button type="button" class="btn btn-floating btn-lg" id="btn-back-to-top"><i class="fas fa-arrow-up"></i></button>
  226. </section>
  227. <div class="modal fade" id="causalsModal" tabindex="-1" aria-labelledby="causalsModalLabel" aria-hidden="true">
  228. <div class="modal-dialog modal-lg">
  229. <div class="modal-content">
  230. <div class="modal-header modal-header-blu">
  231. <h5 class="modal-title" id="causalsModalLabel">
  232. <i class="me-2"></i>
  233. Dettaglio Causali
  234. </h5>
  235. <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="CHIUDI"></button>
  236. </div>
  237. <div class="modal-body">
  238. <div class="row">
  239. <div class="col-12">
  240. <div class="d-flex justify-content-between align-items-center mb-3">
  241. <h6 class="mb-0">
  242. <i class="me-2 text-primary"></i>
  243. Causali incluse:
  244. </h6>
  245. </div>
  246. <div class="border rounded" style="max-height: 400px; overflow-y: auto;">
  247. <ul id="causalsList" class="list-group list-group-flush mb-0">
  248. <!-- Causals will be populated here by JavaScript -->
  249. </ul>
  250. </div>
  251. </div>
  252. </div>
  253. </div>
  254. <div class="modal-footer" style="background-color: #FFF!important;">
  255. <button type="button" class="btn--ui lightGrey me-2" data-bs-dismiss="modal">CHIUDI</button>
  256. </div>
  257. </div>
  258. </div>
  259. </div>
  260. <div class="modal fade" id="exportModal" tabindex="-1" aria-labelledby="exportModalLabel" aria-hidden="true">
  261. <div class="modal-dialog">
  262. <div class="modal-content">
  263. <div class="modal-header modal-header-blu">
  264. <h5 class="modal-title" id="exportModalLabel">Seleziona Periodo per Export</h5>
  265. <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="CHIUDI"></button>
  266. </div>
  267. <div class="modal-body">
  268. <div class="row g-3">
  269. <div class="col-md-6">
  270. <label for="exportFromDate" class="form-label">Data Inizio</label>
  271. <input type="date" class="form-control" id="exportFromDate" wire:model.defer="exportFromDate">
  272. </div>
  273. <div class="col-md-6">
  274. <label for="exportToDate" class="form-label">Data Fine</label>
  275. <input type="date" class="form-control" id="exportToDate" wire:model.defer="exportToDate">
  276. </div>
  277. </div>
  278. <div class="row mt-4">
  279. <div class="col-12">
  280. <div class="form-check export-method-check">
  281. <input class="form-check-input" type="checkbox" id="sendViaEmail" wire:model.defer="sendViaEmail">
  282. <label class="form-check-label" for="sendViaEmail">
  283. <i class="fas fa-envelope me-2"></i>Invia via Email
  284. <small class="d-block text-muted mt-1">L'export verrà elaborato in background e inviato alla tua email</small>
  285. </label>
  286. </div>
  287. </div>
  288. </div>
  289. <div class="row mt-3" style="display: none;" id="emailAddressRow">
  290. <div class="col-12">
  291. <label for="exportEmailAddress" class="form-label">
  292. <i class="fas fa-envelope me-1"></i>Indirizzo Email
  293. </label>
  294. <input type="email" class="form-control" id="exportEmailAddress"
  295. wire:model.defer="exportEmailAddress"
  296. placeholder="inserisci@email.com">
  297. <div class="invalid-feedback" id="emailValidationFeedback">
  298. Inserisci un indirizzo email valido
  299. </div>
  300. <small class="form-text text-muted">
  301. Il file Excel verrà inviato a questo indirizzo
  302. </small>
  303. </div>
  304. </div>
  305. <div class="row mt-3" style="display: none;" id="emailSubjectRow">
  306. <div class="col-12">
  307. <label for="exportEmailSubject" class="form-label">
  308. <i class="fas fa-tag me-1"></i>Oggetto Email
  309. </label>
  310. <input type="text" class="form-control" id="exportEmailSubject"
  311. wire:model.defer="exportEmailSubject"
  312. placeholder="Prima Nota - Export">
  313. <small class="form-text text-muted">
  314. Personalizza l'oggetto dell'email
  315. </small>
  316. </div>
  317. </div>
  318. <div class="row mt-3">
  319. <div class="col-12">
  320. <div class="alert alert-info d-flex align-items-start">
  321. <i class="fas fa-info-circle me-2 mt-1"></i>
  322. <div>
  323. <strong>Informazioni Export:</strong>
  324. <ul class="mb-0 mt-1">
  325. <li>L'export includerà tutti i record nel periodo selezionato</li>
  326. <li>Verranno applicati i filtri attualmente attivi</li>
  327. <li id="emailProcessingInfo" style="display: none;">L'elaborazione avverrà in background, potrai continuare a usare l'applicazione</li>
  328. </ul>
  329. </div>
  330. </div>
  331. </div>
  332. </div>
  333. </div>
  334. <div class="modal-footer" style="background-color: #FFF!important;">
  335. <button type="button" class="btn--ui lightGrey me-2" data-bs-dismiss="modal">ANNULLA</button>
  336. <button type="button" class="btn--ui primary" onclick="handleExportClick()" id="exportButton">
  337. <span id="loadingState" style="display: none;">
  338. <div class="spinner-border spinner-border-sm me-2" role="status">
  339. <span class="visually-hidden">Loading...</span>
  340. </div>
  341. ELABORAZIONE...
  342. </span>
  343. <span id="normalState">
  344. <i class="fas fa-download me-1"></i>
  345. ESPORTA
  346. </span>
  347. </button>
  348. </div>
  349. </div>
  350. </div>
  351. </div>
  352. <div class="toast-container position-fixed top-0 end-0 p-3" style="z-index: 11000;">
  353. <!-- Toasts will be dynamically added here -->
  354. </div>
  355. </div>
  356. @push('scripts')
  357. <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
  358. @endpush
  359. @push('scripts')
  360. <link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
  361. <style>
  362. .loading-overlay {
  363. position: absolute;
  364. top: 0;
  365. left: 0;
  366. right: 0;
  367. bottom: 0;
  368. background-color: rgba(255, 255, 255, 0.9);
  369. display: flex;
  370. justify-content: center;
  371. align-items: center;
  372. z-index: 1000;
  373. border-radius: 4px;
  374. }
  375. .loading-content {
  376. text-align: center;
  377. color: var(--color-blu);
  378. }
  379. .loading-content i {
  380. margin-bottom: 15px;
  381. color: var(--color-blu);
  382. }
  383. .loading-content p {
  384. margin: 0;
  385. font-size: 16px;
  386. font-weight: 500;
  387. color: #10172A;
  388. }
  389. .modal {
  390. z-index: 9999 !important;
  391. }
  392. .modal-backdrop {
  393. z-index: 9998 !important;
  394. background-color: rgba(0, 0, 0, 0.6) !important;
  395. }
  396. .modal-content {
  397. border-radius: 8px;
  398. border: none;
  399. box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
  400. z-index: 10000 !important;
  401. }
  402. .modal-header {
  403. color: white;
  404. border-bottom: none;
  405. border-radius: 8px 8px 0 0;
  406. }
  407. .modal-header .btn-close {
  408. filter: invert(1);
  409. }
  410. .modal-title {
  411. font-weight: 600;
  412. }
  413. .varie-link:hover {
  414. color: #084c6b !important;
  415. text-decoration: underline !important;
  416. }
  417. #btn-back-to-top {
  418. background-color: var(--color-blu);
  419. color: white;
  420. position: fixed;
  421. display: none;
  422. }
  423. #btn-back-to-bottom {
  424. background-color: var(--color-blu);
  425. color: white;
  426. position: fixed;
  427. z-index: 9999;
  428. display: none;
  429. }
  430. button[disabled] {
  431. opacity: 0.7;
  432. cursor: not-allowed;
  433. }
  434. .btn--ui .fa-spinner {
  435. margin-right: 5px;
  436. }
  437. .scrollTable {
  438. margin-left: 0px;
  439. margin-right: 0px;
  440. padding: 15px;
  441. overflow-x: auto;
  442. overflow-y: auto;
  443. white-space: nowrap;
  444. border: 1px solid #ddd;
  445. }
  446. ::-webkit-scrollbar-thumb {
  447. background: #e4e4e4;
  448. border-radius: 10px;
  449. }
  450. table thead {
  451. position: sticky;
  452. z-index: 100;
  453. top: 0;
  454. }
  455. .select2-container--default .select2-selection--single {
  456. background-color: #E9F0F5;
  457. border: 0.0625rem solid #DFE5EB;
  458. font-size: 0.75rem;
  459. height: 38px !important;
  460. }
  461. .select2-selection__rendered {
  462. padding-top: 3px;
  463. }
  464. .select2 {
  465. width: 100% !important;
  466. }
  467. .select2-selection--multiple {
  468. overflow: hidden !important;
  469. height: auto !important;
  470. }
  471. .select2-container {
  472. box-sizing: border-box;
  473. display: inline-block;
  474. margin: 0;
  475. position: relative;
  476. vertical-align: middle;
  477. z-index: 999 !important;
  478. }
  479. .select2-dropdown {
  480. z-index: 999 !important;
  481. }
  482. .select2-container .select2-selection--single {
  483. box-sizing: border-box;
  484. cursor: pointer;
  485. display: block;
  486. height: 38px;
  487. user-select: none;
  488. -webkit-user-select: none;
  489. }
  490. .select2-container .select2-selection--single .select2-selection__rendered {
  491. display: block;
  492. padding-left: 8px;
  493. padding-right: 20px;
  494. overflow: hidden;
  495. text-overflow: ellipsis;
  496. white-space: nowrap;
  497. }
  498. button#exportDropdown.btn--ui_outline.light {
  499. font-weight: normal !important;
  500. }
  501. .btn--ui_outline.light.dropdown-toggle:active,
  502. .btn--ui_outline.light.dropdown-toggle:focus,
  503. .btn--ui_outline.light.dropdown-toggle.show {
  504. background-color: transparent !important;
  505. color: #10172A !important;
  506. box-shadow: none !important;
  507. }
  508. .btn--ui_outline.light.dropdown-toggle:hover {
  509. background-color: transparent !important;
  510. color: #10172A !important;
  511. }
  512. .form-select {
  513. height: 38px !important;
  514. }
  515. .form-control {
  516. height: 43px !important;
  517. }
  518. #exportModal .modal-body {
  519. padding: 1.5rem;
  520. }
  521. #exportModal .form-label {
  522. font-weight: 600;
  523. color: #10172A;
  524. margin-bottom: 0.5rem;
  525. }
  526. #exportModal .text-muted {
  527. font-size: 0.875rem;
  528. }
  529. .btn--ui[disabled] .fa-spinner {
  530. margin-right: 0.5rem;
  531. }
  532. body.modal-open {
  533. overflow: hidden;
  534. }
  535. .modal-dialog {
  536. z-index: 10001 !important;
  537. margin: 1.75rem auto;
  538. }
  539. .list-group-item {
  540. border-left: none;
  541. border-right: none;
  542. border-top: 1px solid #dee2e6;
  543. padding: 12px 15px;
  544. }
  545. .list-group-item:first-child {
  546. border-top: none;
  547. }
  548. .list-group-item:last-child {
  549. border-bottom: none;
  550. }
  551. @media (max-width: 768px) {
  552. .col-md-2, .col-md-3, .col-md-4 {
  553. margin-bottom: 10px;
  554. }
  555. .prima--nota_buttons {
  556. float: none !important;
  557. margin-top: 10px !important;
  558. text-align: center;
  559. }
  560. }
  561. .export-method-check {
  562. padding: 16px 16px 16px 50px;
  563. background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
  564. border-radius: 8px;
  565. border: 2px solid #e9ecef;
  566. transition: all 0.3s ease;
  567. cursor: pointer;
  568. position: relative;
  569. }
  570. .export-method-check:hover {
  571. border-color: var(--color-blu);
  572. background: linear-gradient(135deg, #e8f4f8 0%, #d1ecf1 100%);
  573. }
  574. .export-method-check .form-check-input {
  575. position: absolute;
  576. left: 16px;
  577. top: 50%;
  578. transform: translateY(-50%);
  579. margin: 0;
  580. width: 20px;
  581. height: 20px;
  582. background-color: #fff;
  583. border: 2px solid #dee2e6;
  584. border-radius: 4px;
  585. cursor: pointer;
  586. }
  587. .export-method-check .form-check-input:checked {
  588. background-color: var(--color-blu);
  589. border-color: var(--color-blu);
  590. }
  591. .export-method-check .form-check-input:checked ~ .form-check-label {
  592. color: var(--color-blu);
  593. font-weight: 600;
  594. }
  595. .export-method-check .form-check-label {
  596. font-weight: 500;
  597. color: #495057;
  598. cursor: pointer;
  599. margin-left: 0;
  600. display: block;
  601. }
  602. .form-check-input:focus {
  603. border-color: var(--color-blu);
  604. outline: 0;
  605. box-shadow: 0 0 0 0.2rem rgba(12, 97, 151, 0.25);
  606. }
  607. #emailAddressRow.show, #emailSubjectRow.show {
  608. display: block !important;
  609. animation: slideDown 0.3s ease-out;
  610. }
  611. @keyframes slideDown {
  612. from {
  613. opacity: 0;
  614. transform: translateY(-10px);
  615. }
  616. to {
  617. opacity: 1;
  618. transform: translateY(0);
  619. }
  620. }
  621. .invalid-feedback {
  622. display: none;
  623. }
  624. .is-invalid ~ .invalid-feedback {
  625. display: block;
  626. }
  627. .alert-info {
  628. background-color: rgba(12, 97, 151, 0.1);
  629. border-color: rgba(12, 97, 151, 0.2);
  630. color: var(--color-blu);
  631. }
  632. .spinner-border-sm {
  633. width: 1rem;
  634. height: 1rem;
  635. }
  636. .toast {
  637. min-width: 300px;
  638. }
  639. .toast-body {
  640. font-weight: 500;
  641. }
  642. .btn--ui:disabled {
  643. opacity: 0.7;
  644. cursor: not-allowed;
  645. }
  646. .list-group-item {
  647. border-left: none;
  648. border-right: none;
  649. border-top: 1px solid #dee2e6;
  650. padding: 12px 15px;
  651. }
  652. .list-group-item:first-child {
  653. border-top: none;
  654. }
  655. .list-group-item:last-child {
  656. border-bottom: none;
  657. }
  658. /* Enhanced styles for the causal modal with amounts */
  659. .list-group-item.d-flex {
  660. display: flex !important;
  661. justify-content: space-between !important;
  662. align-items: center !important;
  663. }
  664. .list-group-item .badge {
  665. font-size: 0.875rem;
  666. font-weight: 600;
  667. }
  668. .list-group-item:hover {
  669. background-color: rgba(12, 97, 151, 0.05);
  670. transition: background-color 0.2s ease;
  671. }
  672. #causalsModal .modal-body {
  673. padding: 1rem 0;
  674. }
  675. </style>
  676. <script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
  677. <script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
  678. <script src="/assets/js/aCollapTable.js"></script>
  679. @endpush
  680. @push('scripts')
  681. <script>
  682. function closeSelect2Dropdowns() {
  683. $('.filterCausals').each(function() {
  684. if ($(this).hasClass('select2-hidden-accessible')) {
  685. $(this).select2('close');
  686. }
  687. });
  688. $('.filterMember').each(function() {
  689. if ($(this).hasClass('select2-hidden-accessible')) {
  690. $(this).select2('close');
  691. }
  692. });
  693. }
  694. function load() {
  695. $(document).ready(function(){
  696. $(document).on("keypress", $('.filterCausals'), function (e) {
  697. setTimeout(() => {
  698. $(".select2-results__option").each(function(){
  699. var txt = $(this).html();
  700. var count = (txt.match(/-/g) || []).length;
  701. $(this).addClass('paddingLeftSelect' + count);
  702. });
  703. }, 100);
  704. });
  705. if (!$('.filterCausals').hasClass('select2-hidden-accessible')) {
  706. $('.filterCausals').select2({
  707. "language": {"noResults": function(){return "Nessun risultato";}},
  708. "dropdownParent": $('body'),
  709. "width": "100%"
  710. });
  711. }
  712. $('.filterCausals').off('change.customHandler').on('change.customHandler', function (e) {
  713. var data = $('.filterCausals').select2("val");
  714. @this.set('filterCausals', data);
  715. });
  716. $('.filterCausals').off('select2:open.customHandler').on('select2:open.customHandler', function (e) {
  717. if ($('#causalsModal').hasClass('show')) {
  718. $('#causalsModal').modal('hide');
  719. }
  720. setTimeout(() => {
  721. $(".select2-results__option").each(function(){
  722. var txt = $(this).html();
  723. var count = (txt.match(/-/g) || []).length;
  724. $(this).addClass('paddingLeftSelect' + count);
  725. });
  726. }, 100);
  727. });
  728. if (!$('.filterMember').hasClass('select2-hidden-accessible')) {
  729. $('.filterMember').select2({
  730. "language": {"noResults": function(){return "Nessun risultato";}},
  731. "dropdownParent": $('body'),
  732. "width": "100%"
  733. });
  734. }
  735. $('.filterMember').off('change.customHandler').on('change.customHandler', function (e) {
  736. var data = $('.filterMember').select2("val");
  737. @this.set('filterMember', data);
  738. });
  739. $('.filterMember').off('select2:open.customHandler').on('select2:open.customHandler', function (e) {
  740. if ($('#causalsModal').hasClass('show')) {
  741. $('#causalsModal').modal('hide');
  742. }
  743. });
  744. });
  745. }
  746. function printData() {
  747. var divToPrint = document.getElementById("tablesaw-350");
  748. newWin = window.open("");
  749. var htmlToPrint = '' +
  750. '<style type="text/css">' +
  751. 'table {' +
  752. 'border-collapse:collapse;' +
  753. 'border:1px solid #000;' +
  754. '}' +
  755. 'table th, table td, table tr {' +
  756. 'border:1px solid #000;' +
  757. 'padding:0.5em;' +
  758. '}' +
  759. '</style>';
  760. htmlToPrint += divToPrint.outerHTML;
  761. newWin.document.write(htmlToPrint);
  762. newWin.document.close();
  763. newWin.print();
  764. newWin.close();
  765. }
  766. function scrollFunction() {
  767. const element = document.getElementById('resume-table');
  768. const mybuttonBottom = document.getElementById("btn-back-to-bottom");
  769. const mybutton = document.getElementById("btn-back-to-top");
  770. if (element.scrollTop > 20) {
  771. mybutton.style.display = "block";
  772. mybuttonBottom.style.display = "block";
  773. } else {
  774. mybutton.style.display = "none";
  775. mybuttonBottom.style.display = "none";
  776. }
  777. }
  778. function backToTop() {
  779. $('#resume-table').scrollTop(0);
  780. }
  781. function backToBottom() {
  782. $('#resume-table').scrollTop($('#resume-table')[0].scrollHeight);
  783. }
  784. $(document).ready(function() {
  785. load();
  786. document.querySelector("#print")?.addEventListener("click", function(){
  787. printData();
  788. });
  789. const element = document.getElementById('resume-table');
  790. element.onscroll = scrollFunction;
  791. const mybuttonBottom = document.getElementById("btn-back-to-bottom");
  792. const mybutton = document.getElementById("btn-back-to-top");
  793. mybutton.addEventListener("click", backToTop);
  794. mybuttonBottom.addEventListener("click", backToBottom);
  795. $(document).on('click', '.varie-link', function(e) {
  796. e.preventDefault();
  797. e.stopPropagation();
  798. closeSelect2Dropdowns();
  799. const causalsData = $(this).data('causals');
  800. if (causalsData) {
  801. const causals = causalsData.split('|');
  802. $('#causalsList').empty();
  803. causals.forEach(function(causal) {
  804. if (causal.trim()) {
  805. if (causal.includes(':::')) {
  806. const parts = causal.split(':::');
  807. const causalName = parts[0].trim();
  808. const amount = parts[1].trim();
  809. $('#causalsList').append(
  810. '<li class="list-group-item d-flex justify-content-between align-items-center">' +
  811. '<div>' +
  812. '<i class="fas fa-tags me-2" style="color: var(--color-blu);"></i>' +
  813. causalName +
  814. '</div>' +
  815. '<span class="badge bg-primary rounded-pill" style="background-color: var(--color-blu) !important;">' +
  816. amount +
  817. '</span>' +
  818. '</li>'
  819. );
  820. } else {
  821. $('#causalsList').append(
  822. '<li class="list-group-item">' +
  823. '<i class="fas fa-tags me-2" style="color: var(--color-blu);"></i>' +
  824. causal.trim() +
  825. '</li>'
  826. );
  827. }
  828. }
  829. });
  830. $('#causalsModal').modal('show');
  831. $('#causalsModal').on('shown.bs.modal', function () {
  832. $(this).find('.btn-close').focus();
  833. });
  834. }
  835. });
  836. });
  837. Livewire.on('load-table', () => {
  838. load();
  839. });
  840. Livewire.on('load-select', () => {
  841. load();
  842. });
  843. Livewire.on('filters-reset', () => {
  844. $('.filterMember').val('').trigger('change');
  845. $('.filterCausals').val('').trigger('change');
  846. load();
  847. });
  848. Livewire.on('show-export-modal', () => {
  849. $('#exportModal').modal('show');
  850. });
  851. Livewire.on('hide-export-modal', () => {
  852. $('#exportModal').modal('hide');
  853. });
  854. function showToast(type, message, duration = 5000) {
  855. const toastContainer = document.querySelector('.toast-container');
  856. if (!toastContainer) {
  857. console.error('Toast container not found');
  858. return;
  859. }
  860. const toastId = 'toast-' + Date.now();
  861. const toastColors = {
  862. success: 'bg-success',
  863. error: 'bg-danger',
  864. warning: 'bg-warning',
  865. info: 'bg-info'
  866. };
  867. const toastIcons = {
  868. success: 'fa-check-circle',
  869. error: 'fa-exclamation-circle',
  870. warning: 'fa-exclamation-triangle',
  871. info: 'fa-info-circle'
  872. };
  873. const toast = document.createElement('div');
  874. toast.id = toastId;
  875. toast.className = `toast align-items-center text-white ${toastColors[type]} border-0`;
  876. toast.setAttribute('role', 'alert');
  877. toast.innerHTML = `
  878. <div class="d-flex">
  879. <div class="toast-body">
  880. <i class="fas ${toastIcons[type]} me-2"></i>
  881. ${message}
  882. </div>
  883. <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
  884. </div>
  885. `;
  886. toastContainer.appendChild(toast);
  887. if (typeof bootstrap !== 'undefined') {
  888. const bsToast = new bootstrap.Toast(toast, { delay: duration });
  889. bsToast.show();
  890. toast.addEventListener('hidden.bs.toast', function() {
  891. if (toastContainer.contains(toast)) {
  892. toastContainer.removeChild(toast);
  893. }
  894. });
  895. return bsToast;
  896. } else {
  897. toast.style.display = 'block';
  898. setTimeout(() => {
  899. if (toastContainer.contains(toast)) {
  900. toastContainer.removeChild(toast);
  901. }
  902. }, duration);
  903. }
  904. }
  905. document.addEventListener('DOMContentLoaded', function() {
  906. const sendViaEmailCheckbox = document.getElementById('sendViaEmail');
  907. const emailAddressRow = document.getElementById('emailAddressRow');
  908. const emailSubjectRow = document.getElementById('emailSubjectRow');
  909. const emailProcessingInfo = document.getElementById('emailProcessingInfo');
  910. const exportIcon = document.getElementById('exportIcon');
  911. const exportButtonText = document.getElementById('exportButtonText');
  912. const emailInput = document.getElementById('exportEmailAddress');
  913. function toggleEmailFields() {
  914. if (sendViaEmailCheckbox && sendViaEmailCheckbox.checked) {
  915. if (emailAddressRow) {
  916. emailAddressRow.style.display = 'block';
  917. emailAddressRow.classList.add('show');
  918. }
  919. if (emailSubjectRow) {
  920. emailSubjectRow.style.display = 'block';
  921. emailSubjectRow.classList.add('show');
  922. }
  923. if (emailProcessingInfo) {
  924. emailProcessingInfo.style.display = 'list-item';
  925. }
  926. if (exportIcon) exportIcon.className = 'fas fa-paper-plane me-1';
  927. if (exportButtonText) exportButtonText.textContent = 'INVIA EMAIL';
  928. } else {
  929. if (emailAddressRow) {
  930. emailAddressRow.style.display = 'none';
  931. emailAddressRow.classList.remove('show');
  932. }
  933. if (emailSubjectRow) {
  934. emailSubjectRow.style.display = 'none';
  935. emailSubjectRow.classList.remove('show');
  936. }
  937. if (emailProcessingInfo) {
  938. emailProcessingInfo.style.display = 'none';
  939. }
  940. if (exportIcon) exportIcon.className = 'fas fa-download me-1';
  941. if (exportButtonText) exportButtonText.textContent = 'ESPORTA';
  942. }
  943. }
  944. function validateEmail(email) {
  945. const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  946. return emailRegex.test(email);
  947. }
  948. if (sendViaEmailCheckbox) {
  949. sendViaEmailCheckbox.addEventListener('change', toggleEmailFields);
  950. }
  951. if (emailInput) {
  952. emailInput.addEventListener('blur', function() {
  953. if (sendViaEmailCheckbox && sendViaEmailCheckbox.checked && this.value) {
  954. if (validateEmail(this.value)) {
  955. this.classList.remove('is-invalid');
  956. this.classList.add('is-valid');
  957. } else {
  958. this.classList.remove('is-valid');
  959. this.classList.add('is-invalid');
  960. }
  961. }
  962. });
  963. emailInput.addEventListener('input', function() {
  964. this.classList.remove('is-invalid', 'is-valid');
  965. });
  966. }
  967. if (typeof $ !== 'undefined') {
  968. $('#exportModal').on('shown.bs.modal', function() {
  969. toggleEmailFields();
  970. });
  971. }
  972. });
  973. document.addEventListener('livewire:load', function () {
  974. console.log('Livewire loaded, setting up export event listeners');
  975. Livewire.on('export-email-queued', function() {
  976. console.log('Export email queued event received');
  977. showToast('info',
  978. '<strong>Export avviato!</strong><br>' +
  979. 'L\'elaborazione è in corso in background. Riceverai l\'email a breve.',
  980. 8000
  981. );
  982. });
  983. Livewire.on('export-email-sent', function() {
  984. console.log('Export email sent event received');
  985. showToast('success',
  986. '<strong>Email inviata!</strong><br>' +
  987. 'L\'export è stato completato e inviato alla tua email.',
  988. 6000
  989. );
  990. });
  991. Livewire.on('export-email-error', function(message) {
  992. console.log('Export email error event received:', message);
  993. showToast('error',
  994. '<strong>Errore nell\'export:</strong><br>' +
  995. (message || 'Si è verificato un errore durante l\'elaborazione.'),
  996. 10000
  997. );
  998. });
  999. Livewire.on('show-export-modal', function() {
  1000. console.log('Show export modal event received');
  1001. if (typeof $ !== 'undefined') {
  1002. $('#exportModal').modal('show');
  1003. }
  1004. });
  1005. Livewire.on('hide-export-modal', function() {
  1006. console.log('Hide export modal event received');
  1007. if (typeof $ !== 'undefined') {
  1008. $('#exportModal').modal('hide');
  1009. }
  1010. });
  1011. });
  1012. if (typeof Livewire !== 'undefined') {
  1013. document.addEventListener('livewire:initialized', function () {
  1014. console.log('Livewire initialized, setting up export event listeners');
  1015. Livewire.on('export-email-queued', function() {
  1016. showToast('info',
  1017. '<strong>Export avviato!</strong><br>' +
  1018. 'L\'elaborazione è in corso in background. Riceverai l\'email a breve.',
  1019. 8000
  1020. );
  1021. });
  1022. Livewire.on('export-email-sent', function() {
  1023. showToast('success',
  1024. '<strong>Email inviata!</strong><br>' +
  1025. 'L\'export è stato completato e inviato alla tua email.',
  1026. 6000
  1027. );
  1028. });
  1029. Livewire.on('export-email-error', function(message) {
  1030. showToast('error',
  1031. '<strong>Errore nell\'export:</strong><br>' +
  1032. (message || 'Si è verificato un errore durante l\'elaborazione.'),
  1033. 10000
  1034. );
  1035. });
  1036. Livewire.on('show-export-modal', function() {
  1037. if (typeof $ !== 'undefined') {
  1038. $('#exportModal').modal('show');
  1039. }
  1040. });
  1041. Livewire.on('hide-export-modal', function() {
  1042. if (typeof $ !== 'undefined') {
  1043. $('#exportModal').modal('hide');
  1044. }
  1045. });
  1046. });
  1047. }
  1048. window.addEventListener('load', function() {
  1049. if (typeof showToast === 'function') {
  1050. console.log('showToast function is available globally');
  1051. } else {
  1052. console.error('showToast function is not available globally');
  1053. }
  1054. });
  1055. function handleExportClick() {
  1056. showExportLoading();
  1057. @this.call('exportWithDateRange');
  1058. }
  1059. function showExportLoading() {
  1060. document.getElementById('normalState').style.display = 'none';
  1061. document.getElementById('loadingState').style.display = 'inline-flex';
  1062. document.getElementById('exportButton').disabled = true;
  1063. }
  1064. function hideExportLoading() {
  1065. document.getElementById('normalState').style.display = 'inline-flex';
  1066. document.getElementById('loadingState').style.display = 'none';
  1067. document.getElementById('exportButton').disabled = false;
  1068. }
  1069. // Listen for when export is complete
  1070. Livewire.on('export-complete', function() {
  1071. hideExportLoading();
  1072. });
  1073. Livewire.on('hide-export-modal', function() {
  1074. hideExportLoading();
  1075. });
  1076. </script>
  1077. @endpush