Skip to content

Commit

Permalink
add absensi operator
Browse files Browse the repository at this point in the history
  • Loading branch information
Bagas Udi Sahsangka committed Sep 24, 2021
1 parent 16babe2 commit b0dcde7
Show file tree
Hide file tree
Showing 55 changed files with 332 additions and 29 deletions.
26 changes: 26 additions & 0 deletions app/Http/Controllers/AbsensiOperatorController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace App\Http\Controllers;

use App\Models\AbsensiOperator;
use Illuminate\Http\Request;

class AbsensiOperatorController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
return AbsensiOperator::with(['user:id,name'])->when($request->keyword, function ($q) use ($request) {
$q->whereHas('user', function ($q) use ($request) {
$q->where('name', 'LIKE', "%{$request->keyword}%");
});
})->when($request->date, function ($q) use ($request) {
$q->whereRaw('DATE(login) BETWEEN ? AND ? OR DATE(logout) BETWEEN ? AND ?', [...$request->date, ...$request->date]);
})->orderBy($request->sort_prop ?: 'updated_at', $request->sort_order ?: 'desc')
->paginate($request->pageSize);
}
}
1 change: 1 addition & 0 deletions app/Http/Controllers/UserLogController.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public function index(Request $request)

return UserLog::selectRaw('user_logs.*, users.name AS user')
->join('users', 'users.id', '=', 'user_logs.user_id')
->where('users.name', '!=', 'controller')
->when($request->keyword, function ($q) use ($request) {
$q->where(function ($q) use ($request) {
$q->where('users.name', 'LIKE', '%' . $request->keyword . '%')
Expand Down
32 changes: 32 additions & 0 deletions app/Models/AbsensiOperator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class AbsensiOperator extends Model
{
use HasFactory;

protected $fillable = ['user_id', 'login', 'logout'];

protected $appends = ['durasi'];

public function user()
{
return $this->belongsTo(User::class);
}

public function getDurasiAttribute()
{
if (!$this->logout) {
return '';
}

$login = new \DateTime($this->login);
$logout = new \DateTime($this->logout);
$interval = $login->diff($logout);
return $interval->format('%dH %H:%I:%S');
}
}
18 changes: 18 additions & 0 deletions app/Models/UserLog.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,22 @@
class UserLog extends Model
{
protected $fillable = ['user_id', 'action'];

public function user()
{
return $this->belongsTo(User::class);
}

public static function booted()
{
static::created(function ($model) {
if ($model->action == 'LOGIN') {
AbsensiOperator::create(['user_id' => $model->user_id, 'login' => $model->created_at]);
} else {
AbsensiOperator::whereNull('logout') // jam logoutnya masih null
->where('user_id', $model->user_id) // user yg sama
->update(['logout' => $model->created_at]);
}
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateAbsensiOperatorsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('absensi_operators', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->dateTime('login');
$table->dateTime('logout')->nullable();
$table->timestamps();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('absensi_operators');
}
}
141 changes: 141 additions & 0 deletions frontend/components/AbsensiOperator.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<template>
<div>
<el-form inline class="text-right" @submit.native.prevent>
<el-form-item>
<el-date-picker
style="margin-top: 5px"
size="small"
@change="searchData"
v-model="filters.date"
format="dd-MMM-yyyy"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="Dari"
end-placeholder="Sampai"
>
</el-date-picker>
</el-form-item>
<el-form-item>
<el-input
size="small"
v-model="filters.keyword"
placeholder="Cari"
prefix-icon="el-icon-search"
clearable
@change="searchData"
>
</el-input>
</el-form-item>

<el-form-item>
<el-button
icon="el-icon-refresh"
@click="refreshData"
size="small"
type="primary"
></el-button>
</el-form-item>
</el-form>

<el-table
:data="tableData.data"
stripe
height="calc(100vh - 310px)"
v-loading="loading"
@sort-change="sortChange"
>
<el-table-column
prop="created_at"
label="Tanggal"
sortable="custom"
show-overflow-tooltip
min-width="150px"
>
<template slot-scope="{ row }">
{{ $moment(row.created_at).format('DD/MMM/YY') }}
</template>
</el-table-column>

<el-table-column
prop="user.name"
label="User"
show-overflow-tooltip
min-width="150px"
>
<template slot-scope="{ row }">
{{ row.user.name }}
</template>
</el-table-column>

<el-table-column
prop="login"
label="Login"
sortable="custom"
show-overflow-tooltip
min-width="150px"
>
<template slot-scope="{ row }">
{{ $moment(row.login).format('DD/MMM/YY HH:mm:ss') }}
</template>
</el-table-column>

<el-table-column
prop="logout"
label="Logout"
sortable="custom"
show-overflow-tooltip
min-width="150px"
>
<template slot-scope="{ row }">
{{
row.logout ? $moment(row.logout).format('DD/MMM/YY HH:mm:ss') : ''
}}
</template>
</el-table-column>

<el-table-column
prop="durasi"
label="Durasi"
show-overflow-tooltip
min-width="150px"
>
</el-table-column>
</el-table>

<br />

<el-pagination
class="text-right"
background
@current-change="currentChange"
@size-change="sizeChange"
layout="total, sizes, prev, pager, next"
:page-size="pageSize"
:page-sizes="[10, 25, 50, 100]"
:total="tableData.total"
></el-pagination>
</div>
</template>

<script>
import crud from '@/mixins/crud'
export default {
mixins: [crud],
props: ['date'],
watch: {
range(v) {
this.requestData()
},
},
data() {
return {
url: '/api/absensiOperator',
}
},
}
</script>
6 changes: 0 additions & 6 deletions frontend/components/notification/UserLog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,6 @@
<el-table
:data="tableData.data"
stripe
@row-dblclick="
(row, column, event) => {
snapshot = row.snapshot
showSnapshot = true
}
"
height="calc(100vh - 310px)"
v-loading="loading"
@sort-change="sortChange"
Expand Down
3 changes: 1 addition & 2 deletions frontend/mixins/crud.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,8 @@ export default {
.catch(() => console.log(e))
},

searchData(v) {
searchData() {
this.page = 1
this.keyword = v
this.requestData()
},

Expand Down
4 changes: 4 additions & 0 deletions frontend/pages/notification.vue
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@
<NotificationSnapshot />
</el-tab-pane>

<el-tab-pane lazy label="ABSENSI OPERATOR">
<AbsensiOperator :date="filters.dateRange" />
</el-tab-pane>

<el-tab-pane lazy label="LOG USER">
<NotificationUserLog :range="filters.dateRange" />
</el-tab-pane>
Expand Down
4 changes: 2 additions & 2 deletions public/200.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<!doctype html>
<html lang="en" data-n-head="%7B%22lang%22:%7B%221%22:%22en%22%7D%7D">
<head>
<title>MITRATEKNIK PARKING SYSTEM</title><meta data-n-head="1" charset="utf-8"><meta data-n-head="1" name="viewport" content="width=device-width,initial-scale=1"><meta data-n-head="1" data-hid="description" name="description" content=""><meta data-n-head="1" name="format-detection" content="telephone=no"><link data-n-head="1" rel="icon" type="image/x-icon" href="/favicon.ico"><link rel="preload" href="/_nuxt/70c7bc8.js" as="script"><link rel="preload" href="/_nuxt/7935040.js" as="script"><link rel="preload" href="/_nuxt/1c443f4.js" as="script"><link rel="preload" href="/_nuxt/20da6db.js" as="script">
<title>MITRATEKNIK PARKING SYSTEM</title><meta data-n-head="1" charset="utf-8"><meta data-n-head="1" name="viewport" content="width=device-width,initial-scale=1"><meta data-n-head="1" data-hid="description" name="description" content=""><meta data-n-head="1" name="format-detection" content="telephone=no"><link data-n-head="1" rel="icon" type="image/x-icon" href="/favicon.ico"><link rel="preload" href="/_nuxt/f495b58.js" as="script"><link rel="preload" href="/_nuxt/7935040.js" as="script"><link rel="preload" href="/_nuxt/0355a19.js" as="script"><link rel="preload" href="/_nuxt/1345864.js" as="script">
</head>
<body>
<div id="__nuxt"><style>#nuxt-loading{background:#fff;visibility:hidden;opacity:0;position:absolute;left:0;right:0;top:0;bottom:0;display:flex;justify-content:center;align-items:center;flex-direction:column;animation:nuxtLoadingIn 10s ease;-webkit-animation:nuxtLoadingIn 10s ease;animation-fill-mode:forwards;overflow:hidden}@keyframes nuxtLoadingIn{0%{visibility:hidden;opacity:0}20%{visibility:visible;opacity:0}100%{visibility:visible;opacity:1}}@-webkit-keyframes nuxtLoadingIn{0%{visibility:hidden;opacity:0}20%{visibility:visible;opacity:0}100%{visibility:visible;opacity:1}}#nuxt-loading>div,#nuxt-loading>div:after{border-radius:50%;width:5rem;height:5rem}#nuxt-loading>div{font-size:10px;position:relative;text-indent:-9999em;border:.5rem solid #f5f5f5;border-left:.5rem solid #000;-webkit-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0);-webkit-animation:nuxtLoading 1.1s infinite linear;animation:nuxtLoading 1.1s infinite linear}#nuxt-loading.error>div{border-left:.5rem solid #ff4500;animation-duration:5s}@-webkit-keyframes nuxtLoading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes nuxtLoading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}</style><script>window.addEventListener("error",function(){var e=document.getElementById("nuxt-loading");e&&(e.className+=" error")})</script><div id="nuxt-loading" aria-live="polite" role="status"><div>Loading...</div></div></div><script>window.__NUXT__={config:{_app:{basePath:"/",assetsPath:"/_nuxt/",cdnURL:null}}}</script>
<script src="/_nuxt/70c7bc8.js"></script><script src="/_nuxt/7935040.js"></script><script src="/_nuxt/1c443f4.js"></script><script src="/_nuxt/20da6db.js"></script></body>
<script src="/_nuxt/f495b58.js"></script><script src="/_nuxt/7935040.js"></script><script src="/_nuxt/0355a19.js"></script><script src="/_nuxt/1345864.js"></script></body>
</html>
1 change: 1 addition & 0 deletions public/_nuxt/0217007.js

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions public/_nuxt/0355a19.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions public/_nuxt/0cd5256.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit b0dcde7

Please sign in to comment.