diff --git a/Dockerfile b/Dockerfile
index af287d814eae8b400bb56ab8c3d837fbd5714ba6..943cc9dca09157a17e8bdcad3a7594cc79769d85 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -9,6 +9,8 @@ RUN apt-get update && apt-get install -y \
     libcrypt-openssl-x509-perl \
     libdata-guid-perl \
     libdata-random-perl \
+    libdatetime-perl \
+    libdatetime-event-recurrence-perl \
     libdata-validate-uri-perl \
     libdbix-class-perl \
     libdbd-pg-perl \
diff --git a/VERSION b/VERSION
index 26aaba0e86632e4d537006e45b0ec918d780b3b4..f0bb29e76388856b273698ae6064b0380ce5e5d2 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.2.0
+1.3.0
diff --git a/lib/PZ.pm b/lib/PZ.pm
index 96d5e1376cd5c2c6786c619b6d39005e82ce3a6e..cb5f4885e08e8ab2da6605afec85e31a15d5f661 100644
--- a/lib/PZ.pm
+++ b/lib/PZ.pm
@@ -103,7 +103,9 @@ sub startup {
 
     $r->get('/')->to(cb => sub { shift->render('index'); });
     $r->post('/')->to('Shortcut#create');
-    $r->get('/shortcuts')->to(cb => sub { shift->render('shortcuts'); });
+    $r->get('/shortcuts')->to(cb => sub { shift->render('shortcuts-vue'); });
+    $r->get('/shortcuts/:id')->to('Shortcut#get1');
+    $r->get('/shortcuts/:id/log.csv')->to('Log#csv');
 
     $r->get('/:shortcut')->to('Shortcut#redirect');
     $r->get('/:shortcut/qr.png')->to('Shortcut#qr');
diff --git a/lib/PZ/Controller/Log.pm b/lib/PZ/Controller/Log.pm
new file mode 100644
index 0000000000000000000000000000000000000000..3a66a82b6d6b67a5799b300615df4685516e0b29
--- /dev/null
+++ b/lib/PZ/Controller/Log.pm
@@ -0,0 +1,62 @@
+package PZ::Controller::Log;
+use Mojo::Base 'Mojolicious::Controller', -signatures;
+
+sub main ($c) {
+    $c->openapi->valid_input or return;
+
+    my $shortcut = $c->stash->{user}->shortcuts({
+        id => $c->stash->{id}
+    })->first;
+
+    return $c->error(404, 'NOT_FOUND') if ! $shortcut;
+
+    my ($log, @result);
+
+    $log = $shortcut->log_items({},
+        {
+            order_by => { -desc => 'time'},
+            rows     => $c->param('page_size'),
+            offset   => $c->param('page_size') * ( $c->param('page_index') - 1 ),
+        }
+    );
+
+    ITEM:
+    while ( my $item = $log->next ) {
+        push @result, {
+            time     => $item->time,
+            ip       => $item->ip,
+            ua       => $item->ua,
+            referrer => $item->referrer,
+        };
+    }
+
+    $c->render(json =>  \@result );
+}
+
+sub csv ($c) {
+
+    my $shortcut = $c->current_user->shortcuts({
+        id => $c->stash->{id}
+    })->first;
+
+    return $c->error(404, 'NOT_FOUND') if ! $shortcut;
+
+    my ($log, @result);
+
+    $log = $shortcut->log_items({},
+        {
+            order_by => { 'time'},
+        }
+    );
+
+    $c->res->headers->content_type('text/csv');
+    $c->res->headers->content_disposition(
+        'attachment; filename=log.csv',
+    );
+    $c->render(
+        template =>'log.csv',
+        log      => $log,
+    );
+}
+1;
+
diff --git a/lib/PZ/Controller/Shortcut.pm b/lib/PZ/Controller/Shortcut.pm
index 3d60b5d372d439e8a8cd7bc98439a12b8af2bcf2..e7e494161b68bae216e2be486f175a8f0d05b729 100644
--- a/lib/PZ/Controller/Shortcut.pm
+++ b/lib/PZ/Controller/Shortcut.pm
@@ -85,7 +85,10 @@ sub list ($c) {
     my @shortcuts = ();
 
     SHORTCUT:
-    foreach my $shortcut ( $c->stash->{user}->shortcuts({ deleted => undef }) ) {
+    foreach my $shortcut ( $c->stash->{user}->shortcuts(
+        { deleted  => undef },
+        { order_by => 'shortcut' },
+    ) ) {
         push @shortcuts, $c->spec_filter(
             { $shortcut->get_columns }, 'Shortcut'
         );
@@ -94,6 +97,34 @@ sub list ($c) {
     $c->render(json =>  \@shortcuts,  );
 }
 
+sub get ($c) {
+
+    my $shortcut = $c->stash->{user}->shortcuts({
+        id => $c->stash->{id}
+    })->first;
+
+    if ( ! $shortcut ) {
+        $c->render( status => 404, text => 'not found' );
+        return;
+    }
+
+    $c->render(json =>  { $shortcut->get_columns }   );
+}
+
+sub get1 ($c) {
+
+    my $shortcut = $c->current_user->shortcuts({
+        id => $c->stash->{id}
+    })->first;
+
+    if ( ! $shortcut ) {
+        $c->render( status => 404, text => 'not found' );
+        return;
+    }
+
+    $c->stash->{shortcut} = $shortcut;
+    $c->stash->{template} = 'shortcut';
+}
 sub update ($c) {
 
     my $shortcut = $c->stash->{user}->shortcuts({
diff --git a/lib/PZ/Controller/Stat.pm b/lib/PZ/Controller/Stat.pm
new file mode 100644
index 0000000000000000000000000000000000000000..504a9806e2ddf05b81f715d79263042520da5ea2
--- /dev/null
+++ b/lib/PZ/Controller/Stat.pm
@@ -0,0 +1,34 @@
+package PZ::Controller::Stat;
+use Mojo::Base 'Mojolicious::Controller', -signatures;
+
+use DateTime;
+
+sub main ($c) {
+    my $shortcut = $c->stash->{user}->shortcuts({
+        id => $c->stash->{id}
+    })->first;
+
+    return $c->error(404, 'NOT_FOUND') if ! $shortcut;
+
+    my %tz = (time_zone => 'Europe/Prague');
+    my $begin = DateTime->from_epoch(%tz, epoch => $c->param('begin') / 1000);
+    my $end   = DateTime->from_epoch(%tz, epoch => $c->param('end') / 1000);
+
+    my ($stat, @result);
+
+    $stat = $shortcut->stat_daily_items(period => {
+          between => [$begin, $end]
+    });
+
+    ITEM:
+    while ( my $item = $stat->next ) {
+        push @result, {
+            period => $item->period,
+            count  => $item->count,
+        };
+    }
+
+    $c->render(json =>  \@result );
+}
+
+1;
diff --git a/lib/PZ/Schema/Result/Shortcut.pm b/lib/PZ/Schema/Result/Shortcut.pm
index 372b6f8bce544fee9a38435f980b87d41c6ebf33..e5219d1186bcf691fca3224852ebdb27dbfc9408 100644
--- a/lib/PZ/Schema/Result/Shortcut.pm
+++ b/lib/PZ/Schema/Result/Shortcut.pm
@@ -48,7 +48,7 @@ __PACKAGE__->has_many(
 );
 
 __PACKAGE__->has_many(
-    stat_dayly_items => 'PZ::Schema::Result::StatDayly',
+    stat_daily_items => 'PZ::Schema::Result::StatDaily',
     { 'foreign.shortcut_id' => 'self.id', },
 );
 
diff --git a/openapi.yaml b/openapi.yaml
index 78115fe46d19bba512e51fbf571cf180c95534d6..c6200926de0b7489a0fe0b18a0a5ea7e2d611fa8 100644
--- a/openapi.yaml
+++ b/openapi.yaml
@@ -38,6 +38,31 @@ components:
           type: integer
           description: Kód přesměrování
           enum: [301, 302]
+    StatisticItem:
+      type: object
+      properties:
+        period:
+          type: string
+          description: Obdobi
+        count:
+          type: integer
+          description: PoÄŤet
+    LogItem:
+      type: object
+      properties:
+        timestamp:
+          type: string
+          description: Datum a cas
+        ip:
+          type: string
+          description: IP adresa
+        ua:
+          type: string
+          description: User Agent
+        referrer:
+          type: string
+          description: HTTP Referrer
+
   securitySchemes:
     Token:
       type: apiKey
@@ -82,6 +107,21 @@ paths:
                   $ref: '#/components/schemas/Shortcut'
 
   /shortcuts/{id}:
+    get:
+      tags:
+      - shortcuts
+      security:
+        - Token: []
+      summary: "Zkratka"
+      operationId: ShortcutGet
+      x-mojo-to: shortcut#get
+      responses:
+        204:
+          description: Shortcut
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Shortcut'
     put:
       tags:
       - shortcuts
@@ -110,3 +150,85 @@ paths:
       responses:
         204:
           description: Shortcut deleted
+
+  /shortcuts/{id}/stat/:
+    get:
+      tags:
+      - shortcut
+      - statistic
+      security:
+        - Token: []
+      summary: "Statistika pro zkratku"
+      operationId: ShortcutStatistic
+      x-mojo-to: Stat#main
+      parameters:
+      - name: id
+        in: path
+        required: true
+        example: 100345
+        description: "Identifikator zkratky"
+        schema:
+          type: integer
+      - name: begin
+        in: query
+        required: true
+        description: "Zacatek"
+        schema:
+          type: integer
+      - name: end
+        in: query
+        required: true
+        description: "Konec"
+        schema:
+          type: integer
+      responses:
+        200:
+          description: Statistika
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: '#/components/schemas/StatisticItem'
+
+  /shortcuts/{id}/log:
+    get:
+      tags:
+      - shortcuts
+      - statistic
+      security:
+        - Token: []
+      summary: "Log pro zkratku"
+      operationId: ShortcutLog
+      x-mojo-to: Log#main
+      parameters:
+      - name: id
+        in: path
+        required: true
+        example: 100345
+        description: "Identifikator zkratky"
+        schema:
+          type: integer
+      - name: page_size
+        in: query
+        example: 100
+        description: "PoÄŤet zaznamu na strance"
+        schema:
+          type: integer
+          default: 1000
+      - name: page_index
+        in: query
+        example: 1
+        description: "Stranka"
+        schema:
+          type: integer
+          default: 1
+      responses:
+        200:
+          description: Log navstev pro zkratku
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: '#/components/schemas/LogItem'
diff --git a/templates/layouts/default.html.ep b/templates/layouts/default.html.ep
index 2ce503355249a7b20b3f9f171720e5375007150e..6a96274de156fa6f8c04c824b2d924f849c1a23f 100644
--- a/templates/layouts/default.html.ep
+++ b/templates/layouts/default.html.ep
@@ -30,7 +30,6 @@
  <script type="text/javascript" src="https://cdn-cdnjs-cloudflare.pirati.cz/ajax/libs/jsgrid/1.5.3/jsgrid.min.js"></script>
  <script src="https://cdn-unpkg.pirati.cz/vue@2.7.8/dist/vue.min.js"></script>
  <script src="<%= config->{styleguide} %>js/main.bundle.js"></script>
-
   <link rel="stylesheet" href="/custom.css"/>
 
 </head>
diff --git a/templates/log.csv.html.ep b/templates/log.csv.html.ep
new file mode 100644
index 0000000000000000000000000000000000000000..588624b7734d45bc67d87944e08fc766f5cfa9ef
--- /dev/null
+++ b/templates/log.csv.html.ep
@@ -0,0 +1,2 @@
+"datum a ÄŤas","ip adresa","browser","referrer"<%= "\x0D\x0A" =%><% while (my $entry =  $log->next) { =%>"<%= $entry->time =%>","<%= $entry->ip =%>","<%= $entry->ua =%>","<%= $entry->referrer =%>"<%= "\x0D\x0A" =%><% } =%>
+
diff --git a/templates/shortcut.html.ep b/templates/shortcut.html.ep
new file mode 100644
index 0000000000000000000000000000000000000000..2081706b224cdd1f9f50340a912e21a5a1c98e14
--- /dev/null
+++ b/templates/shortcut.html.ep
@@ -0,0 +1,206 @@
+% layout 'default';
+
+<h1 class="head-alt-md md:head-alt-lg max-w-5xl mb-8">Zkratka "<%= $shortcut->shortcut %>"</h1>
+% if (0) {
+<h2 class="head-alt-sm my-4">Editace zkratky</h2>
+
+<form id="Edit" class="mb-8">
+
+<div class="form-field form-field--error form-field--required mb-4">
+  <label class="form-field__label" for="url">URL</label>
+  <div class="form-field__wrapper form-field__wrapper--shadowed">
+    <input type="text" class="text-input form-field__control form-field--required" value="" v-model="shortcut.url" id="url" />
+  </div>
+  <div class="form-field__error" v-if="shortcut.url === ''"></div>
+</div>
+
+<div class="form-field form-field--error form-field--required mb-4">
+  <label class="form-field__label" for="code">Typ přesměrování</label>
+  <div class="form-field__wrapper form-field__wrapper--shadowed select">
+    <select v-model="shortcut.code"  class="select__control form-field__control ">
+        <option value="301">301 trvalé</option>
+        <option value="302">302 dočasné</option>
+    </select>
+  </div>
+  <div class="form-field__error" v-if="shortcut.url === ''"></div>
+</div>
+
+<button class="btn Xbtn--blue-300 btn--hoveractive" @click.prevent="updateShortcut">
+ <div class="btn__body">Uložit změny</div>
+</button>
+<button class="btn Xbtn--red-600 btn--hoveractive" @click.prevent="delete_confirm_visible=true">
+ <div class="btn__body">Smazat zkratku</div>
+</button>
+
+<div class="modal__overlay toggle-modal-sample-1" id="modal-sample-1" v-if="delete_confirm_visible" v-cloak>
+  <div class="modal__content" role="dialog">
+    <div class="modal__container w-full max-w-2xl" role="dialog">
+      <div class="modal__container-body elevation-10">
+        <button class="modal__close" title="Zavřít" @click.prevent="delete_confirm_visible = false"><i class="ico--cross"></i></button>
+        <div class="card ">
+          <div class="card__body ">
+            <h1 class="card-headline mb-2">Smazat zratku</h1>
+            <p class="card-body-text my-8">
+               Opravdu chcete smazat zkratku?
+            </p>
+
+            <p class="card-body-text">
+              <button class="btn btn--green-300 btn--hoveractive text-sm" @click.prevent="deleteMeet()">
+               <div class="btn__body"><i class="btn__inline-icon ico--bin"></i>ANO</div>
+              </button>
+              <button class="btn btn--orange-400 btn--hoveractive text-sm" @click.prevent="delete_confirm_visible = false">
+               <div class="btn__body"><i class="btn__inline-icon ico--cross"></i>NE</div>
+              </button>
+            </p>
+
+          </div>
+        </div>
+
+      </div>
+    </div>
+  </div>
+</div>
+</form>
+% }
+<h2 class="head-alt-sm my-4">Statistika navštěv</h2>
+<div class="mb-8" style="width:100%; height: 600px;"><canvas id="stat"></canvas></div>
+
+<div class="mb-4 flex justify-between">
+
+    <h2 class="head-alt-sm">Log navštěv</h2>
+    <div>
+        <button class="btn btn--orange-400 btn--hoveractive text-sm">
+            <div class="btn__body"><i class="btn__inline-icon ico--download"></i><a href="/shortcuts/<%= $shortcut->id %>/log.csv">Stahnout CSV</a></div>
+        </button>
+   </div>
+</div>
+<div id="log"></div>
+
+<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
+<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns/dist/chartjs-adapter-date-fns.bundle.min.js"></script>
+
+<script>
+  const end = Date.now();
+  const begin = Date.now() - 31 * 24 * 3600 * 1000;
+
+  const ctx = document.getElementById('stat');
+
+  var chart = new Chart(ctx, {
+    type: 'bar',
+    data: {
+      datasets: [{
+        label: 'PoÄŤet klikĹŻ',
+        data: [],
+        borderWidth: 1
+      }]
+    },
+    options: {
+      scales: {
+        y: {
+          beginAtZero: true,
+          ticks: {
+              stepSize: 1
+          },
+        },
+        x: {
+            min: begin,
+            max: end,
+
+            type: 'time',
+            display: true,
+            offset: true,
+            time: {
+                unit: 'day',
+                tooltipFormat: 'dd.MM.yyyy',
+                displayFormats: {
+                    day: 'dd.MM.yyyy'
+                }
+            }
+        },
+      },
+      parsing: {
+        xAxisKey: 'period',
+        yAxisKey: 'count'
+      }
+    }
+  });
+
+  fetch('/api/shortcuts/<%= $shortcut->id %>/stat/?begin=' + begin + '&end=' + end , {
+    headers: { 'X-Auth-Token': '<%= $c->current_user->token %>' },
+  })
+  .then((response) => response.json())
+  .then((data) => {
+        chart.data.datasets[0].data = data;
+        chart.update();
+  }
+  );
+
+  $("#log").jsGrid({
+      width: "100%",
+      height: "auto",
+
+      inserting: false,
+      editing: false,
+      sorting: true,
+      paging: true,
+      selecting: false,
+      autoload: true,
+
+      controller: {
+          loadData: function(filter) {
+
+              return $.ajax({
+                  url: "/api/shortcuts/<%= $shortcut->id %>/log/",
+                  dataType: "json",
+                  headers: { 'X-Auth-Token': '<%= $c->current_user->token %>' },
+                  data: filter,
+              });
+          },
+      },
+
+      fields: [
+          { type: "text", name: "time", title: "Datum a ÄŤas", width: '11em' },
+          { type: "text", name: "ip", title: "IP", width: '8em' },
+          { type: "text", title: "Referrer", name: "referrer", width: '100%' },
+      ]
+  });
+
+// form
+% if (0) {
+
+
+  const BASE_URL = "/api/shortcuts";
+  const API_HEADERS     = {
+      "Content-Type": "application/json",
+      "Accept": "application/json",
+      "X-Auth-Token": "<%= current_user->token %>",
+  };
+
+  var form = new Vue({
+    el: '#Edit',
+
+    data: {
+        shortcut: [],
+        delete_confirm_visible: false,
+    },
+
+    methods: {
+        fetchData: function() {
+          fetch(BASE_URL + '/<%= $shortcut->id %>', {
+            headers: API_HEADERS,
+          })
+            .then((res) => res.json())
+            .then(res => {
+                this.shortcut = res;
+            })
+        },
+    }
+  });
+
+  form.fetchData();
+% }
+</script>
+
+
+
+</script>
diff --git a/templates/shortcuts-vue.html.ep b/templates/shortcuts-vue.html.ep
new file mode 100644
index 0000000000000000000000000000000000000000..e94e20065fc8e6c3791f84caf13da94d289a7434
--- /dev/null
+++ b/templates/shortcuts-vue.html.ep
@@ -0,0 +1,53 @@
+% layout 'default';
+
+<h1 class="head-alt-md md:head-alt-lg max-w-5xl mb-8">Moje zkratky</h1>
+
+<table id="Shortcuts" class="table table-fixed table--striped" v-cloak>
+  <thead>
+    <tr>
+      <th>Zkratka</th>
+      <th>URL</th>
+      <th>Přesměrování</th>
+    </tr>
+  </thead>
+  <tbody>
+  <tr v-for="shortcut in shortcuts" class="cursor-pointer" @click="window.location.href ='/shortcuts/' + shortcut.id">
+    <td class="head-xs">{{shortcut.shortcut}}</td>
+    <td class="w-96">{{ shortcut.url }}</td>
+    <td class="">{{ shortcut.code == 301 ? '301 trvalé' : '302 dočasné'}}</td>
+   </tr>
+  </tbody>
+
+</table>
+
+<script type="module">
+  const BASE_URL = "/api/shortcuts";
+  const API_HEADERS     = {
+      "Content-Type": "application/json",
+      "Accept": "application/json",
+      "X-Auth-Token": "<%= current_user->token %>",
+  };
+
+  var list = new Vue({
+    el: '#Shortcuts',
+
+    data: {
+        shortcuts: [],
+    },
+
+    methods: {
+        fetchData: function() {
+          fetch(BASE_URL, {
+            headers: API_HEADERS,
+          })
+            .then((res) => res.json())
+            .then(res => {
+                this.shortcuts = res;
+            })
+        },
+    }
+  });
+
+  list.fetchData();
+
+</script>
diff --git a/templates/shortcuts.html.ep b/templates/shortcuts.html.ep
index 1c7fa00001f7f3e6f5ccf1fdeadf746e4628d955..0ddf3817181bb7c93328e1b3f3482a4b6dcf8389 100644
--- a/templates/shortcuts.html.ep
+++ b/templates/shortcuts.html.ep
@@ -86,7 +86,13 @@ $(function() {
                 valueField: "code",
                 textField: "name"
             },
-            { type: "control", editButton: false, width: 60 }
+            { type: "text", title: "Statistika", name: "id", editing: false,
+              itemTemplate: function(value) {
+                 return '<a href="/shortcuts/' + value + '">' + value + '</a>';
+              },
+             },
+             { type: "control", editButton: false, width: 60 },
+
         ]
     });
 });