repos
/ timestrap-django master

timestrap-django

mirror archived upstream

Time tracking you can host anywhere, built on Django. Full export support in multiple formats and easily extensible.

djangodockerhandcodedpythonself-hostedtime-trackingtimetracker

2.8 KB · 115 lines · vue Raw History
  1<template>
  2<div
  3  v-if="$perms.view_entry"
  4  class="container-fluid">
  5  <entry-modal
  6    v-if="modalShow"
  7    :entry="modalEntry"
  8    @close="modalShow = false"/>
  9
 10  <chart :entries="entries"/>
 11
 12  <div id="entry-rows">
 13    <div
 14      v-for="(entryBlock, blockIndex) in entries"
 15      :index="blockIndex"
 16      :key="entryBlock.id">
 17      <div class="row inset-row">
 18        <div class="col-6">
 19          <h2 class="display-4">
 20            {{ $moment(entryBlock.date).format('ddd[,] MMMM Do') }}
 21          </h2>
 22        </div>
 23        <div class="col-6 d-flex align-items-center justify-content-end h4 mb-0">
 24          <span class="badge badge-success mb-0">
 25            {{ $moment.duration(entryBlock.duration, 'hours').format('h[h] m[m]') }}
 26          </span>
 27        </div>
 28      </div>
 29      <div>
 30        <template v-if="entryBlock.entries.length > 0">
 31          <entry
 32            v-for="(entry, entryIndex) in entryBlock.entries"
 33            :entry="entry"
 34            :index="entryIndex"
 35            :key="entry.id"
 36            :editable="editable"
 37            @modal="modalToggle(entry)"
 38            @delete-entry="deleteEntry(entry)"/>
 39        </template>
 40        <template v-else>
 41          <div class="entry row py-3 bg-light small">
 42            <div class="col">
 43              <strong>No entries</strong> for this day.
 44            </div>
 45          </div>
 46        </template>
 47      </div>
 48    </div>
 49
 50    <div class="row bg-success text-white py-2 border-0">
 51      <div class="ml-auto col-sm-2 text-right">
 52        Subtotal<br>
 53        <strong>Total</strong>
 54      </div>
 55      <div class="col-sm-4">
 56        <icon
 57          :icon="['fas', 'clock']"
 58          class="mr-1"/>
 59        {{ $moment.duration(subtotal, 'hours').format('d[d] h[h] m[m]') }}<br>
 60        <icon
 61          :icon="['fas', 'clock']"
 62          class="mr-1"/>
 63        <strong>{{ $moment.duration(total, 'hours').format('d[d] h[h] m[m]') }}</strong>
 64      </div>
 65    </div>
 66  </div>
 67</div>
 68</template>
 69
 70
 71<script>
 72import {mapGetters, mapActions, mapState} from 'vuex';
 73
 74import Datepicker from '../datepicker.vue';
 75import Entry from '../entry.vue';
 76import EntryModal from './entry-modal.vue';
 77import Chart from './chart.vue';
 78
 79
 80export default {
 81  components: {
 82    Datepicker,
 83    Entry,
 84    EntryModal,
 85    Chart,
 86  },
 87  data() {
 88    return {
 89      editable: true,
 90      modalEntry: null,
 91      modalShow: false,
 92    };
 93  },
 94  computed: {
 95    ...mapState({
 96      total: state => state.entries.total,
 97    }),
 98    ...mapGetters({
 99      entries: 'entries/getEntriesByDay',
100      subtotal: 'entries/getEntriesByDayTotal',
101    }),
102  },
103  methods: {
104    ...mapActions('entries', [
105      'fetchEntries',
106    ]),
107    modalToggle: function(entry) {
108      if (typeof(entry) !== 'undefined') this.modalEntry = entry;
109      else this.modalEntry = null;
110      this.modalShow = !this.modalShow;
111    },
112  },
113};
114</script>