templates/application/index.html.twig line 1

Open in your IDE?
  1. {% extends 'base.html.twig' %}
  2. {% block title %}Applications{% endblock %}
  3. {% block content %}
  4.     <!-- Page Header -->
  5.     <div class="d-flex align-items-center justify-content-between mb-3">
  6.         <div class="d-flex align-items-center">
  7.             <div class="bg-primary bg-opacity-10 rounded d-flex align-items-center justify-content-center me-3" style="width: 40px; height: 40px;">
  8.                 <i data-lucide="file-text" class="text-primary" style="width: 20px; height: 20px;"></i>
  9.             </div>
  10.             <div>
  11.                 <h4 class="mb-0 fw-semibold">Applications</h4>
  12.                 <span class="text-muted small">{{ applications.totalItemCount }} total applications</span>
  13.             </div>
  14.         </div>
  15.         <div class="d-flex gap-2">
  16.             <button type="button" class="btn btn-outline-primary btn-sm" data-bs-toggle="modal" data-bs-target="#exportApplicationModal">
  17.                 <i data-lucide="download" style="width: 14px; height: 14px;" class="me-1"></i> Export
  18.             </button>
  19.             <button type="button" class="btn btn-outline-primary btn-sm" data-bs-toggle="modal" data-bs-target="#exportHistoryModal">
  20.                 <i data-lucide="clock" style="width: 14px; height: 14px;" class="me-1"></i> Export History
  21.             </button>
  22.             {% if not is_granted('ROLE_READ_ONLY') %}
  23.                 <a href="{{ path('application_create') }}" class="btn btn-primary btn-sm">
  24.                     <i data-lucide="plus" style="width: 14px; height: 14px;" class="me-1"></i> New Application
  25.                 </a>
  26.             {% endif %}
  27.         </div>
  28.     </div>
  29.     <!-- Filters -->
  30.     {% include 'application/_partials/filters.html.twig' %}
  31.     <!-- Applications Table -->
  32.     <div class="card">
  33.         <div class="card-body p-0">
  34.             <div class="table-responsive">
  35.                 <table class="table table-sm table-hover mb-0">
  36.                     <thead class="bg-light">
  37.                     <tr class="small">
  38.                         <th class="border-0" style="width: 25%;">Company</th>
  39.                         <th class="border-0">MCC</th>
  40.                         <th class="border-0">Instance</th>
  41.                         <th class="border-0">Created</th>
  42.                         <th class="border-0" style="width: 28%;">Products & Status</th>
  43.                         <th class="border-0 text-center">Type</th>
  44.                     </tr>
  45.                     </thead>
  46.                     <tbody>
  47.                     {% for application in applications.items %}
  48.                         {% set firstProduct = application.product_statuses is defined and application.product_statuses|length > 0 ? application.product_statuses|first : null %}
  49.                         {% set rowUrl = application.app_token and firstProduct ? path('application_view', {token: application.app_token, product: firstProduct.product_name|default('')|lower|replace({' ': '-', '_': '-'})}) : '#' %}
  50.                         <tr style="cursor: pointer;" onclick="window.location='{{ rowUrl }}';">
  51.                             <td>
  52.                                 <div class="d-flex align-items-center text-decoration-none text-reset">
  53.                                     <div class="flex-shrink-0 me-2">
  54.                                         <div class="bg-secondary bg-opacity-10 rounded d-flex align-items-center justify-content-center" style="width: 32px; height: 32px;">
  55.                                             <i data-lucide="building-2" class="text-secondary" style="width: 16px; height: 16px;"></i>
  56.                                         </div>
  57.                                     </div>
  58.                                     <div class="min-width-0">
  59.                                         <div class="fw-medium small text-truncate">{{ application.comp_legal_name|default('-') }}</div>
  60.                                         {% if application.comp_uic|default('') %}
  61.                                             <code class="small text-muted">{{ application.comp_uic }}</code>
  62.                                         {% endif %}
  63.                                     </div>
  64.                                 </div>
  65.                             </td>
  66.                             <td>
  67.                                 <span class="small">{{ application.ba_mcc|default('-') }}</span>
  68.                             </td>
  69.                             <td>
  70.                                 <span class="badge bg-light text-dark">{{ application.app_instance|instance }}</span>
  71.                             </td>
  72.                             <td>
  73.                                 <span class="small text-muted">
  74.                                     {{ application.app_created_at|date('d/m/Y H:i') }}
  75.                                 </span>
  76.                             </td>
  77.                             <td>
  78.                                 {% if application.product_statuses is defined and application.product_statuses|length > 0 %}
  79.                                     <div class="d-flex flex-wrap gap-1">
  80.                                         {% for productStatus in application.product_statuses %}
  81.                                             {% set productName = productStatus.product_name|default('') %}
  82.                                             {% set status = productStatus.status|default('') %}
  83.                                             {% set statusColor = status == 'approved' ? 'success' : (status == 'rejected' or status == 'declined' ? 'danger' : (status == 'pending' or status == 'under_review' or status == 'in_review' ? 'warning' : 'secondary')) %}
  84.                                             {% set productSlug = productName|lower|replace({' ': '-', '_': '-'}) %}
  85.                                             {% set productUrl = application.app_token ? path('application_view', {token: application.app_token, product: productSlug}) : '#' %}
  86.                                             <a href="{{ productUrl }}" class="text-decoration-none" onclick="event.stopPropagation();">
  87.                                                 <span class="badge bg-{{ statusColor }}-subtle text-{{ statusColor }}" style="font-size: 10px;">
  88.                                                     {{ productName|upper }}
  89.                                                     {% if status %}
  90.                                                         <span class="opacity-75">• {{ status|replace({'_': ' '})|title }}</span>
  91.                                                     {% endif %}
  92.                                                 </span>
  93.                                             </a>
  94.                                         {% endfor %}
  95.                                     </div>
  96.                                 {% else %}
  97.                                     <span class="text-muted small">-</span>
  98.                                 {% endif %}
  99.                             </td>
  100.                             <td class="text-center">
  101.                                 {% if application.app_channel is defined %}
  102.                                     {% if application.app_channel == 'api' %}
  103.                                         <span class="badge bg-info-subtle text-info" data-bs-toggle="tooltip" title="Submitted via API">
  104.                                             <i data-lucide="zap" style="width: 10px; height: 10px;" class="me-1"></i>Auto
  105.                                         </span>
  106.                                     {% elseif application.app_channel == 'admin' %}
  107.                                         <span class="badge bg-primary-subtle text-primary" data-bs-toggle="tooltip" title="Created manually">
  108.                                             <i data-lucide="user" style="width: 10px; height: 10px;" class="me-1"></i>Manual
  109.                                         </span>
  110.                                     {% else %}
  111.                                         <span class="badge bg-secondary-subtle text-secondary">Unknown</span>
  112.                                     {% endif %}
  113.                                 {% else %}
  114.                                     <span class="badge bg-secondary-subtle text-secondary">-</span>
  115.                                 {% endif %}
  116.                             </td>
  117.                         </tr>
  118.                     {% else %}
  119.                         <tr>
  120.                             <td colspan="7" class="text-center py-5 text-muted">
  121.                                 <i data-lucide="file-x" class="mb-2" style="width: 32px; height: 32px;"></i>
  122.                                 <p class="mb-0">No applications found</p>
  123.                                 <p class="small">Try adjusting your filters</p>
  124.                             </td>
  125.                         </tr>
  126.                     {% endfor %}
  127.                     </tbody>
  128.                 </table>
  129.             </div>
  130.         </div>
  131.         {% if applications.totalItemCount > 0 %}
  132.             <div class="card-footer py-2 bg-light">
  133.                 {{ knp_pagination_render(applications) }}
  134.             </div>
  135.         {% endif %}
  136.     </div>
  137.     {% embed 'application/modals/_export-application-modal.html.twig' %}
  138.         {% block export_modal_js %}{% endblock %}
  139.     {% endembed %}
  140.     {% embed 'export/_export-history-modal.html.twig' %}
  141.         {% block export_history_js %}{% endblock %}
  142.     {% endembed %}
  143. {% endblock %}
  144. {% block css %}
  145.     {{ parent() }}
  146.     <style>
  147.         #advancedFilters {
  148.             display: none;
  149.         }
  150.         #advancedFilters.show {
  151.             display: block;
  152.         }
  153.     </style>
  154. {% endblock %}
  155. {% block js %}
  156.     {{ parent() }}
  157.     <script>
  158.         $(document).ready(function() {
  159.             // Initialize Lucide icons
  160.             if (typeof lucide !== 'undefined') {
  161.                 lucide.createIcons();
  162.             }
  163.             
  164.             // Handle advanced filters toggle manually
  165.             var toggleBtn = document.getElementById('toggleAdvancedFilters');
  166.             var advancedFilters = document.getElementById('advancedFilters');
  167.             if (toggleBtn && advancedFilters) {
  168.                 toggleBtn.addEventListener('click', function(e) {
  169.                     e.preventDefault();
  170.                     e.stopPropagation();
  171.                     
  172.                     if (advancedFilters.classList.contains('show')) {
  173.                         advancedFilters.classList.remove('show');
  174.                         toggleBtn.setAttribute('aria-expanded', 'false');
  175.                     } else {
  176.                         advancedFilters.classList.add('show');
  177.                         toggleBtn.setAttribute('aria-expanded', 'true');
  178.                     }
  179.                 });
  180.             }
  181.             
  182.             // Initialize flatpickr for date fields
  183.             if (typeof flatpickr !== 'undefined') {
  184.                 var $fromInput = $('input[name*="createdAtFrom"]');
  185.                 var $toInput = $('input[name*="createdAtTo"]');
  186.                 if ($fromInput.length && $toInput.length) {
  187.                     var fromPicker = flatpickr($fromInput[0], {
  188.                         dateFormat: 'Y-m-d',
  189.                         altInput: true,
  190.                         altFormat: 'd/m/Y',
  191.                         allowInput: true,
  192.                         onChange: function() {
  193.                             var date = this.selectedDates[0] || null;
  194.                             toPicker.set('minDate', date);
  195.                         }
  196.                     });
  197.                     var toPicker = flatpickr($toInput[0], {
  198.                         dateFormat: 'Y-m-d',
  199.                         altInput: true,
  200.                         altFormat: 'd/m/Y',
  201.                         allowInput: true,
  202.                         onChange: function() {
  203.                             if (this.selectedDates[0] && fromPicker.selectedDates[0] && this.selectedDates[0] < fromPicker.selectedDates[0]) {
  204.                                 this.setDate(null);
  205.                                 alert('End date cannot be before start date');
  206.                             }
  207.                         }
  208.                     });
  209.                     $fromInput.on('input', function() {
  210.                         setTimeout(function() {
  211.                             var date = fromPicker.parseDate($fromInput.val(), 'Y-m-d');
  212.                             toPicker.set('minDate', date && !isNaN(date.getTime()) ? date : null);
  213.                         }, 100);
  214.                     });
  215.                 } else {
  216.                     flatpickr('.flatpickr-date', { dateFormat: 'Y-m-d', altInput: true, altFormat: 'd/m/Y', allowInput: true });
  217.                 }
  218.             }
  219.             // Initialize Bootstrap tooltips
  220.             $('[data-bs-toggle="tooltip"]').each(function() {
  221.                 new bootstrap.Tooltip(this);
  222.             });
  223.         });
  224.     </script>
  225.     
  226.     {% embed 'application/modals/_export-application-modal.html.twig' %}
  227.         {% block export_modal_html %}{% endblock %}
  228.         {% block export_modal_js %}{{ parent() }}{% endblock %}
  229.     {% endembed %}
  230.     {% embed 'export/_export-history-modal.html.twig' %}
  231.         {% block export_history_html %}{{ parent() }}{% endblock %}
  232.         {% block export_history_js %}{{ parent() }}{% endblock %}
  233.     {% endembed %}
  234. {% endblock %}