Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 
 

173 rader
9.0 KiB

  1. {# templates/report/times.html.twig #}
  2. {% extends 'base.html.twig' %}
  3. {% set monthsShort = deMonthsShort() %}
  4. {% block title %}{{ 'app.report.page_title'|trans }}{% endblock %}
  5. {% block javascripts %}
  6. {{ parent() }}
  7. {{ encore_entry_script_tags('report') }}
  8. {% endblock %}
  9. {% block body %}
  10. <div class="report-page">
  11. <div class="report-header">
  12. <h1 class="report-header__title">{{ 'app.report.heading'|trans }}</h1>
  13. <div class="report-header__right">
  14. <span class="report-account-name">
  15. <svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" class="report-account-name__icon">
  16. <path d="M10 11a4 4 0 100-8 4 4 0 000 8zM3 17a7 7 0 0114 0" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/>
  17. </svg>
  18. {{ accountName }}
  19. </span>
  20. <nav class="account-tabs">
  21. <a href="{{ path('report_times') }}"
  22. class="account-tab account-tab--active">
  23. {{ 'app.report.tab_times'|trans }}
  24. </a>
  25. <span class="account-tab account-tab--disabled">
  26. {{ 'app.report.tab_projects'|trans }}
  27. </span>
  28. </nav>
  29. </div>
  30. </div>
  31. <div class="report-content">
  32. <div class="report-card">
  33. {# ── Toolbar ──────────────────────────────────────────────────────── #}
  34. <div class="report-toolbar">
  35. <div class="report-toolbar__left">
  36. <span class="report-toolbar__action report-toolbar__action--disabled">
  37. <svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
  38. <circle cx="6.5" cy="6.5" r="4" stroke="currentColor" stroke-width="1.3"/>
  39. <path d="M11 11l2.5 2.5" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/>
  40. </svg>
  41. {{ 'app.report.toolbar_filter'|trans }}
  42. </span>
  43. <span class="report-toolbar__action report-toolbar__action--disabled">
  44. <svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
  45. <path d="M11 2l3 3L5 14H2v-3L11 2z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/>
  46. </svg>
  47. {{ 'app.report.toolbar_edit'|trans }}
  48. </span>
  49. </div>
  50. </div>
  51. {# ── Tabellen-Header ───────────────────────────────────────────────── #}
  52. <div class="report-table">
  53. <div class="report-table__head">
  54. <div class="report-table__cell report-table__cell--date">
  55. {{ 'app.report.col_date'|trans }}
  56. <span class="report-table__sort-icon">▾</span>
  57. </div>
  58. <div class="report-table__cell report-table__cell--client">{{ 'app.report.col_client'|trans }}</div>
  59. <div class="report-table__cell report-table__cell--project">{{ 'app.report.col_project'|trans }}</div>
  60. <div class="report-table__cell report-table__cell--service">{{ 'app.report.col_service'|trans }}</div>
  61. <div class="report-table__cell report-table__cell--user">{{ 'app.report.col_user'|trans }}</div>
  62. <div class="report-table__cell report-table__cell--note">{{ 'app.report.col_note'|trans }}</div>
  63. <div class="report-table__cell report-table__cell--duration">
  64. {{ 'app.report.col_hours'|trans }}
  65. <span class="report-table__summary">{{ totalDuration }}</span>
  66. </div>
  67. <div class="report-table__cell report-table__cell--revenue">
  68. {{ 'app.report.col_revenue'|trans }}
  69. <span class="report-table__summary">{{ totalRevenue|number_format(2, ',', '.') }} €</span>
  70. </div>
  71. <div class="report-table__cell report-table__cell--lock"></div>
  72. </div>
  73. {# ── Einträge ──────────────────────────────────────────────────── #}
  74. {% for entry in entries %}
  75. {% set service = entry.service %}
  76. {% set billable = (service is null or service.billable) %}
  77. {% set hourlyRate = entry.project.client.hourlyRate %}
  78. {% set weekDateStr = entry.date|date('Y-m-d') %}
  79. {% set editUrl = path('timetracking_week_date', {date: weekDateStr}) ~ '?editEntry=' ~ entry.id %}
  80. {% set monthShort = monthsShort[entry.date|date('n') - 1] %}
  81. <div class="report-table__row{% if entry.invoiced %} report-table__row--invoiced{% endif %}"
  82. data-entry-id="{{ entry.id }}"
  83. data-invoiced="{{ entry.invoiced ? 'true' : 'false' }}">
  84. <div class="report-table__cell report-table__cell--date">
  85. <a href="{{ editUrl }}" class="report-table__date-link">
  86. {{ entry.date|date('j') }}. {{ monthShort }} {{ entry.date|date('y') }}
  87. </a>
  88. </div>
  89. <div class="report-table__cell report-table__cell--client">
  90. {{ entry.project.client.name }}
  91. </div>
  92. <div class="report-table__cell report-table__cell--project">
  93. {{ entry.project.name }}
  94. </div>
  95. <div class="report-table__cell report-table__cell--service">
  96. {{ service ? service.name : '' }}
  97. </div>
  98. <div class="report-table__cell report-table__cell--user">
  99. {{ userMap[entry.userId] ?? ('User #' ~ entry.userId) }}
  100. </div>
  101. <div class="report-table__cell report-table__cell--note">
  102. {{ entry.note }}
  103. </div>
  104. <div class="report-table__cell report-table__cell--duration">
  105. {{ entry.durationFormatted }}
  106. </div>
  107. <div class="report-table__cell report-table__cell--revenue">
  108. {% if billable and hourlyRate is not null %}
  109. {{ (hourlyRate * entry.duration / 60)|number_format(2, ',', '.') }} €
  110. {% endif %}
  111. </div>
  112. <div class="report-table__cell report-table__cell--lock">
  113. <button class="report-lock{% if entry.invoiced %} report-lock--invoiced{% endif %}"
  114. data-action="toggle-invoiced"
  115. title="{{ entry.invoiced ? 'app.report.btn_unlock'|trans : 'app.report.btn_lock'|trans }}">
  116. {% include '_atoms/icon-lock.html.twig' %}
  117. </button>
  118. </div>
  119. </div>
  120. {% else %}
  121. <div class="report-table__empty">{{ 'app.report.no_entries'|trans }}</div>
  122. {% endfor %}
  123. {# ── Pagination-Footer ─────────────────────────────────────────── #}
  124. <div class="report-pagination">
  125. <div class="report-pagination__limits">
  126. {{ 'app.report.show'|trans }}
  127. {% for l in validLimits %}
  128. {% if l == limit %}
  129. <strong>{{ l }}</strong>
  130. {% else %}
  131. <a href="{{ path('report_times', {limit: l}) }}">{{ l }}</a>
  132. {% endif %}
  133. {% endfor %}
  134. {{ 'app.report.of_total'|trans({'%count%': totalCount|number_format(0, ',', '.')}) }}
  135. </div>
  136. <span class="report-pagination__duration">{{ totalDuration }}</span>
  137. <span class="report-pagination__revenue">{{ totalRevenue|number_format(2, ',', '.') }} €</span>
  138. <span class="report-pagination__lock-spacer"></span>
  139. </div>
  140. </div>{# /.report-table #}
  141. </div>{# /.report-card #}
  142. </div>{# /.report-content #}
  143. </div>{# /.report-page #}
  144. {% endblock %}