Browse Source

Merge pull request 'add company data' (#38) from dev-wahyun into staging

Reviewed-on: ibnu/generic-ospro-frontend#38
pull/1/head
farhantock 10 months ago
parent
commit
6aa34dad60
  1. 115
      src/views/Master/MasterRoles/index.js
  2. 147
      src/views/Master/RoleProject/index.js
  3. 688
      src/views/SimproV2/Presence/index.js
  4. 45
      src/views/SimproV2/ResourceWorker/index.js

115
src/views/Master/MasterRoles/index.js

@ -16,26 +16,7 @@ const LENGTH_DATA = 10
class index extends Component {
constructor(props) {
let role_id = 0, user_id = 0, isLogin = false, token = '', company_id = 0, all_project = null, role_name='', hierarchy=[], user_name='';
if (props && props.role_id && props.user_id) {
role_id = props.role_id;
user_id = props.user_id;
token = props.token;
isLogin = props.isLogin;
company_id = props.company_id;
all_project = props.all_project;
role_name = props.role_name;
isLogin = props.isLogin;
hierarchy = props.hierarchy;
user_name = props.user_name;
}
super(props)
this.config = {
headers: {
Authorization: `Bearer ${token}`,
"Content-type": "application/json"
}
};
this.state = {
alertDelete: false,
alertNotDelete: false,
@ -61,8 +42,21 @@ class index extends Component {
tooltipTambah: false,
totalPage: 0,
typeDialog: 'Save',
company_id: company_id,
role_name: role_name
company_id: props.company_id || 0,
role_name: props.role_name || '',
role_id: props.role_id || 0,
user_id: props.user_id || 0,
isLogin: props.isLogin || false,
token: props.token || '',
all_project: props.all_project || null,
hierarchy: props.hierarchy || [],
user_name: props.user_name || '',
config: {
headers: {
Authorization: `Bearer ${props.token || ''}`,
"Content-type": "application/json",
}
}
}
this.columns = [
{
@ -84,6 +78,16 @@ class index extends Component {
</Tooltip>
</>,
},
{
title: this.state.role_name === 'Super Admin' ? "Company Name" : null,
dataIndex: "join_first_company_name",
key: "join_first_company_name",
render: (text, record) => {
return this.state.role_name === 'Super Admin' ? (
<span>{record.join_first_company_name}</span>
) : null;
}
},
{ title: this.props.t('nameRole'), dataIndex: 'name', key: 'name', className: "nowrap" },
{ title: this.props.t('description'), dataIndex: 'description', key: 'description' },
]
@ -114,9 +118,18 @@ class index extends Component {
const formData = {
"paging": { "start": start, "length": this.state.rowsPerPage },
"columns": [
{ "name": "name", "logic_operator": "ilike", "value": this.state.search, "operator": "AND" },
],
"columns": [],
group_column: {
"operator": "AND",
"group_operator": "OR",
"where": [
{
"name": "name",
"logic_operator": "~*",
"value": this.state.search,
}
]
},
"joins": [],
"orders": { "columns": ["id"], "ascending": false }
}
@ -128,9 +141,15 @@ class index extends Component {
formData.columns.push(
{ "name": "company_id", "logic_operator": "is null", "value": "", "operator": "AND" },
)
formData.joins.push(
{ "name": "m_company", "column_join": "company_id", "column_results": ["company_name"] }
)
formData.group_column.where.push(
{ name: "company_name", logic_operator: "~*", value: this.state.search, table_name: "m_company" }
)
}
const result = await axios
.post(ROLE_SEARCH, formData, this.config)
.post(ROLE_SEARCH, formData, this.state.config)
.then(res => res)
.catch((error) => error.response);
@ -347,18 +366,42 @@ class index extends Component {
handleExportExcel = async () => {
let start = 0;
let end = "ALL";
const formData = {
"paging": { "start": start, "length": this.state.rowsPerPage },
"columns": [
{ "name": "name", "logic_operator": "ilike", "value": this.state.search, "operator": "AND" }
],
"columns": [],
"group_column": {
"operator": "AND",
"group_operator": "OR",
"where": [
{
"name": "name",
"logic_operator": "~*",
"value": this.state.search,
}
]
},
"joins": [],
"orders": { "columns": ["id"], "ascending": false }
}
if (this.state.role_name !== "Super Admin") {
formData.columns.push(
{ "name": "company_id", "logic_operator": "=", "value": this.state.company_id, "operator": "AND" },
)
} else {
formData.columns.push(
{ "name": "company_id", "logic_operator": "is null", "value": "", "operator": "AND" },
)
formData.joins.push(
{ "name": "m_company", "column_join": "company_id", "column_results": ["company_name"] }
)
formData.group_column.where.push(
{ name: "company_name", logic_operator: "~*", value: this.state.search, table_name: "m_company" }
)
}
const result = await axios
.post(ROLE_SEARCH, formData, this.config)
.post(ROLE_SEARCH, formData, this.state.config)
.then(res => res)
.catch((error) => error.response);
@ -366,10 +409,12 @@ class index extends Component {
const dataRes = result.data.data || [];
const dataExport = [];
dataRes.map((val, index) => {
let row = {
Nama: val.name,
Deskripsi: val.description
}
let row = {};
if (this.state.role_name === 'Super Admin') {
row.Company = val.join_first_company_name;
}
row.Nama = val.name;
row.Deskripsi = val.description;
dataExport.push(row);
})
this.setState({ dataExport: dataExport }, () => {
@ -445,7 +490,7 @@ class index extends Component {
<h4>{this.props.params.name}</h4>
<Row>
<Col>
<Input onChange={this.handleSearch} value={search} type="text" name="search" id="search" placeholder={this.props.t('searchRoles')} />
<Input onChange={this.handleSearch} value={search} type="text" name="search" id="search" placeholder={this.props.t('search')} />
</Col>
<Col>
<Tooltip title={this.props.t('rolesAdd')}>

147
src/views/Master/RoleProject/index.js

@ -9,46 +9,10 @@ import { NotificationContainer, NotificationManager } from 'react-notifications'
import { PROJECT_ROLE_ADD, PROJECT_ROLE_SEARCH, PROJECT_ROLE_EDIT, PROJECT_ROLE_DELETE, ROLEMENU_ADD, ROLEMENU_SEARCH, ROLEMENU_DELETE_ROLE } from '../../../const/ApiConst.js';
import { Pagination, Tooltip, Table } from 'antd';
import { withTranslation } from 'react-i18next';
const token = window.localStorage.getItem('token');
const company_id = localStorage.getItem("company_id")
const role_name = window.localStorage.getItem('role_name');
const BASE_URL = "http://siopas.co.id/custom-php/api/geohr/";
const config = {
headers:
{
Authorization: `Bearer ${token}`,
"Content-type": `application/json`
}
};
const momentFormat = 'HH:mm';
const column = [
{ name: "Nama" },
{ name: "Deskripsi" },
]
const LENGTH_DATA = 10
class index extends Component {
constructor(props) {
let role_id = 0, user_id = 0, isLogin = false, token = '', company_id = 0, all_project = null, role_name='', hierarchy=[], user_name='';
if (props && props.role_id && props.user_id) {
role_id = props.role_id;
user_id = props.user_id;
token = props.token;
isLogin = props.isLogin;
company_id = props.company_id;
all_project = props.all_project;
role_name = props.role_name;
isLogin = props.isLogin;
hierarchy = props.hierarchy;
user_name = props.user_name;
}
super(props)
super(props);
this.state = {
alertDelete: false,
alertNotDelete: false,
@ -74,9 +38,23 @@ class index extends Component {
tooltipTambah: false,
totalPage: 0,
typeDialog: 'Save',
company_id: company_id,
role_name: role_name
}
company_id: props.company_id || 0,
role_name: props.role_name || '',
role_id: props.role_id || 0,
user_id: props.user_id || 0,
isLogin: props.isLogin || false,
token: props.token || '',
all_project: props.all_project || null,
hierarchy: props.hierarchy || [],
user_name: props.user_name || '',
config: {
headers: {
Authorization: `Bearer ${props.token || ''}`,
"Content-type": "application/json",
}
}
};
this.columns = [
{
title: this.props.t('action'),
@ -86,21 +64,27 @@ class index extends Component {
render: (text, record) => <>
<Tooltip title={this.props.t('delete')}>
<i className="fa fa-trash" style={{ color: 'red', marginRight: 10, cursor: "pointer" }} onClick={() => this.handleDelete(text.id)}></i>
</Tooltip>
<Tooltip title={this.props.t('edit')}>
<i className="fa fa-edit" style={{ color: 'green', cursor: "pointer" }} onClick={() => this.handleEdit(text)}></i>
</Tooltip>
</>,
},
{
title: this.state.role_name === 'Super Admin' ? "Company Name" : null,
dataIndex: "join_first_company_name",
key: "join_first_company_name",
render: (text, record) => {
return this.state.role_name === 'Super Admin' ? (
<span>{record.join_first_company_name}</span>
) : null;
}
},
{ title: this.props.t('name'), dataIndex: 'name', key: 'name', className: "nowrap" },
{ title: this.props.t('description'), dataIndex: 'description', key: 'description' },
];
}
async componentDidMount() {
this.getDataRoles();
}
@ -123,9 +107,18 @@ class index extends Component {
const formData = {
"paging": { "start": start, "length": this.state.rowsPerPage },
"columns": [
{ "name": "name", "logic_operator": "ilike", "value": this.state.search, "operator": "AND" },
],
"columns": [],
group_column: {
"operator": "AND",
"group_operator": "OR",
"where": [
{
"name": "name",
"logic_operator": "~*",
"value": this.state.search,
}
]
},
"joins": [],
"orders": { "columns": ["id"], "ascending": false }
}
@ -137,9 +130,15 @@ class index extends Component {
formData.columns.push(
{ "name": "company_id", "logic_operator": "is null", "value": "", "operator": "AND" },
)
formData.joins.push(
{ "name": "m_company", "column_join": "company_id", "column_results": ["company_name"] }
)
formData.group_column.where.push(
{ name: "company_name", logic_operator: "~*", value: this.state.search, table_name: "m_company" }
)
}
const result = await axios
.post(PROJECT_ROLE_SEARCH, formData, config)
.post(PROJECT_ROLE_SEARCH, formData, this.state.config)
.then(res => res)
.catch((error) => error.response);
@ -184,7 +183,7 @@ class index extends Component {
const { idDelete } = this.state
const url = PROJECT_ROLE_DELETE(idDelete)
const result = await axios.delete(url, config)
const result = await axios.delete(url, this.state.config)
.then(res => res)
.catch((error) => error.response);
@ -203,10 +202,10 @@ class index extends Component {
const formData = {
name: data.name,
description: data.description,
company_id
company_id: this.state.company_id
}
const result = await axios.post(PROJECT_ROLE_ADD, formData, config)
const result = await axios.post(PROJECT_ROLE_ADD, formData, this.state.config)
.then(res => res)
.catch((error) => error.response);
@ -224,10 +223,10 @@ class index extends Component {
const formData = {
name: data.name,
description: data.description,
company_id
company_id : this.state.company_id
}
const url = PROJECT_ROLE_EDIT(data.id)
const result = await axios.put(url, formData, config)
const result = await axios.put(url, formData, this.state.config)
.then(res => res)
.catch((error) => error.response);
@ -290,24 +289,50 @@ class index extends Component {
handleExportExcel = async () => {
const payload = {
"paging": { "start": 0, "length": -1 },
"columns": [
{ "name": "name", "logic_operator": "ilike", "value": this.state.search, "operator": "AND" }
],
"columns": [],
"group_column": {
"operator": "AND",
"group_operator": "OR",
"where": [
{
"name": "name",
"logic_operator": "~*",
"value": this.state.search,
}
]
},
"joins": [],
"orders": { "columns": ["id"], "ascending": false }
}
if (this.state.role_name !== "Super Admin") {
payload.columns.push(
{ "name": "company_id", "logic_operator": "=", "value": this.state.company_id, "operator": "AND" },
)
} else {
payload.columns.push(
{ "name": "company_id", "logic_operator": "is null", "value": "", "operator": "AND" },
)
payload.joins.push(
{ "name": "m_company", "column_join": "company_id", "column_results": ["company_name"] }
)
payload.group_column.where.push(
{ name: "company_name", logic_operator: "~*", value: this.state.search, table_name: "m_company" }
)
}
const result = await axios
.post(PROJECT_ROLE_SEARCH, payload, config)
.post(PROJECT_ROLE_SEARCH, payload, this.state.config)
.then(res => res)
.catch((error) => error.response);
if (result && result.data && result.statusText == "OK") {
const dataRes = result.data.data || [];
const dataExport = [];
dataRes.map((val, index) => {
let row = {
Nama: val.name,
Deskripsi: val.description
let row = {};
if (this.state.role_name === 'Super Admin') {
row.Company = val.join_first_company_name;
}
row.Nama = val.name;
row.Deskripsi = val.description;
dataExport.push(row);
})
this.setState({ dataExport: dataExport }, () => {
@ -371,7 +396,7 @@ class index extends Component {
<h4>{this.props.params.name}</h4>
<Row>
<Col>
<Input onChange={this.handleSearch} value={search} type="text" name="search" id="search" placeholder={this.props.t('searchProjectRoles')} />
<Input onChange={this.handleSearch} value={search} type="text" name="search" id="search" placeholder={this.props.t('search')} />
</Col>
<Col>
<Tooltip title={this.props.t('rolesAdd')}>

688
src/views/SimproV2/Presence/index.js

@ -1,339 +1,349 @@
import React, { useState, useEffect, useMemo } from 'react';
import { Card, CardBody, CardHeader, Col, Row, Input } from 'reactstrap';
import { Button } from 'reactstrap';
import axios from 'axios';
import * as XLSX from 'xlsx';
import { NotificationContainer, NotificationManager } from 'react-notifications';
import { Pagination, Tooltip, Table, DatePicker } from 'antd';
import moment from 'moment';
import { PRESENCE_SEARCH, IMAGE_GET_BY_ID } from '../../../const/ApiConst.js';
import DialogFoto from './DialogFoto';
import { useTranslation } from 'react-i18next';
const { RangePicker } = DatePicker;
const token = window.localStorage.getItem('token');
const Index = ({ params }) => {
const [dataTable, setDatatable] = useState([])
const [search, setSearch] = useState('')
const [currentPage, setCurrentPage] = useState(1)
const [totalPage, setTotalPage] = useState(0)
const [rowsPerPage, setRowsPerPage] = useState(10)
const [dataExport, setDataExport] = useState([])
const [startDate, setStartDate] = useState(moment(moment().format("YYYY-M-D")))
const [endDate, setEndDate] = useState(moment(moment().format("YYYY-M-D")))
const [currentDay, setCurrentDay] = useState("today")
const [dataImage, setDataImage] = useState(null)
const [openImage, setOpenImage] = useState(false)
const { t } = useTranslation()
const pageName = params.name;
const config = {
headers:
{
Authorization: `Bearer ${token}`,
"Content-type": `application/json`
}
};
useEffect(() => {
getDataPresence();
}, [search, currentPage, rowsPerPage, startDate, endDate])
useEffect(() => {
const cekData = dataExport || []
if (cekData.length > 0) {
exportExcel()
}
}, [dataExport])
const handleSearch = e => {
const value = e.target.value
setSearch(value);
setCurrentPage(1)
};
const getDataPresence = async () => {
let start = 0;
if (currentPage !== 1 && currentPage > 1) {
start = (currentPage * rowsPerPage) - rowsPerPage
}
let dateStart = moment(startDate).format("YYYY-MM-DD 00:00:00");
let dateEnd = moment(endDate).format("YYYY-MM-DD 23:59:59");
const payload = {
"paging": { "start": start, "length": rowsPerPage },
"columns": [
{ "name": "name", "logic_operator": "ilike", "value": search, "table_name": "m_users" },
{ "name": "clock_in", "logic_operator": "range", "value": dateStart, "value1": dateEnd },
],
"joins": [{
"name": "m_users",
"column_join": "user_id",
"column_results": [
"name",
"ktp_number"
]
}],
"orders": { "columns": ["id"], "ascending": false }
}
const result = await axios
.post(PRESENCE_SEARCH, payload, config)
.then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.code == 200) {
setDatatable(result.data.data);
setTotalPage(result.data.totalRecord);
} else {
NotificationManager.error('Gagal Mengambil Data!!', 'Failed');
}
}
const handleImage = async (id, name) => {
let url = IMAGE_GET_BY_ID(id, "presensi");
const result = await axios
.get(url, config)
.then(res => res)
.catch((error) => error.response);
if (result && result.data.code == 200) {
let dataRes = result.data.data
let dataImage = {
name,
url: dataRes.image
}
await setDataImage(dataImage)
setOpenImage(true)
} else {
NotificationManager.error('Data image tidak ditemukan!', 'Failed');
}
}
const closeDialogImage = () => {
setOpenImage(false)
setDataImage(null)
}
const toggleDialogImage = () => {
if (openImage) {
setDataImage(null)
}
setOpenImage(!openImage)
}
const onShowSizeChange = (current, pageSize) => {
setRowsPerPage(pageSize)
}
const onPagination = (current, pageSize) => {
setCurrentPage(current)
}
const renderDurasiKerja = (jamMasuk, jamKeluar) => {
if (jamMasuk && jamKeluar) {
let start = moment(jamMasuk),
end = moment(jamKeluar);
let diff = end.diff(start);
let result = moment.utc(diff).format('HH:mm:ss');
if (result) {
return result;
} else {
return "-"
}
} else {
return "-"
}
}
const handleExportExcel = async () => {
let dateStart = moment(startDate).format("YYYY-MM-DD 00:00:00");
let dateEnd = moment(endDate).format("YYYY-MM-DD 23:59:59");
const payload = {
"paging": { "start": 0, "length": -1 },
"columns": [
{ "name": "name", "logic_operator": "ilike", "value": search, "table_name": "m_users" },
{ "name": "clock_in", "logic_operator": "range", "value": dateStart, "value1": dateEnd },
],
"joins": [{
"name": "m_users",
"column_join": "user_id",
"column_results": [
"name",
"ktp_number"
]
}],
"orders": { "columns": ["id"], "ascending": false }
}
const result = await axios
.post(PRESENCE_SEARCH, payload, config)
.then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.code == 200) {
let resData = result.data.data;
const excelData = [];
resData.map((val, index) => {
let dataRow = {
"NIK/ID Card": val.join_first_ktp_number ? val.join_first_ktp_number : '-',
"Nama Human Resource": val.join_first_name ? val.join_first_name : '',
"Jam Masuk": val.clock_in ? moment(val.clock_in).format("D-M-YYYY HH:mm:ss") : '-',
"Jam Keluar": val.clock_out ? moment(val.clock_out).format("D-M-YYYY HH:mm:ss") : '-',
"Durasi Kerja": renderDurasiKerja(val.clock_in, val.clock_out),
"Lokasi Masuk": val.clock_in_loc && val.clock_in_loc !== '' ? val.clock_in_loc : '-',
"Lokasi Pulang": val.clock_out_loc && val.clock_out_loc !== '' ? val.clock_out_loc : '-',
"Area Kerja In": val.clock_in_boundary ? "Sesuai" : "Tidak Sesuai",
"Area Kerja Out": val.clock_out_boundary == null ? "-" : val.clock_out_boundary ? "Sesuai" : "Tidak Sesuai",
}
excelData.push(dataRow)
})
await setDataExport(excelData);
} else {
NotificationManager.error('Gagal Export Data!!', 'Failed');
}
}
const exportExcel = () => {
const dataExcel = dataExport || [];
const fileName = `Data ${pageName}.xlsx`;
const ws = XLSX.utils.json_to_sheet(dataExcel);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, `Data ${pageName}`);
XLSX.writeFile(wb, fileName);
setDataExport([])
}
const renderTable = useMemo(() => {
const columns = [
{
title: 'Action',
dataIndex: '',
key: 'x',
render: (text, record) => <>
<Tooltip title={t('image')}>
<i id="TooltipEdit" className="fa fa-image" style={{ color: 'green', cursor: "pointer" }} onClick={() => handleImage(text.id, text.join_first_name)}></i>
</Tooltip>
</>,
},
{ title: t('nik'), dataIndex: 'join_first_ktp_number', key: 'join_first_ktp_number' },
{ title: t('nameHR'), dataIndex: 'join_first_name', key: 'join_first_name' },
{ title: t('presenceIn'), dataIndex: 'clock_in', key: 'clock_in', render: (text, record) => (<div style={{ whiteSpace: "nowrap" }}>{text ? moment(text).format("D-M-YYYY HH:mm:ss") : "-"}</div>) },
{ title: t('presenceOut'), dataIndex: 'clock_out', key: 'clock_out', render: (text, record) => (<div style={{ whiteSpace: "nowrap" }}>{text ? moment(text).format("D-M-YYYY HH:mm:ss") : "-"}</div>) },
{ title: t('workDuration'), render: (text, record) => (<div style={{ whiteSpace: "nowrap" }}>{renderDurasiKerja(record.clock_in, record.clock_out)}</div>) },
{ title: t('locIn'), dataIndex: 'clock_in_loc', key: 'clock_in_loc', render: (text, record) => <>{text && text !== '' ? text : '-'}</> },
{ title: t('locOut'), dataIndex: 'clock_out_loc', key: 'clock_out_loc', render: (text, record) => <>{text && text !== '' ? text : '-'}</> },
{ title: t('workAreaIn'), dataIndex: 'clock_out_loc', key: 'clock_out_loc', render: (text, record) => (<div style={{ whiteSpace: "nowrap", textAlign: "center" }}>{record.clock_in_boundary ? <i className="fa fa-check-circle fa-lg" style={{ color: 'green' }}></i> : <i className="fa fa-times-circle fa-lg" style={{ color: 'red' }}></i>}</div>) },
{ title: t('workAreaOut'), dataIndex: 'clock_out_loc', key: 'clock_out_loc', render: (text, record) => (<div style={{ whiteSpace: "nowrap", textAlign: "center" }}>{record.clock_out_boundary == null ? <i class="fa fa-window-minimize fa-lg" style={{ color: 'orange' }}></i> : record.clock_out_boundary ? <i className="fa fa-check-circle fa-lg" style={{ color: 'green' }}></i> : <i className="fa fa-times-circle fa-lg" style={{ color: 'red' }}></i>}</div>) },
];
return (
<Table
rowKey="id"
size="small"
columns={columns}
dataSource={dataTable}
pagination={false}
/>
)
}, [dataTable])
const handleDatePicker = (date, dateString) => {
setStartDate(date[0])
setEndDate(date[1])
}
const handleChangeDay = (e) => {
const val = e.target.value;
setCurrentDay(val)
if (val === "today") {
setStartDate(moment(moment().format("YYYY-M-D")))
setEndDate(moment(moment().format("YYYY-M-D")))
setCurrentPage(1)
} else if (val === "3 day") {
setStartDate(moment(moment().subtract(3, "days").format("YYYY-M-D")))
setEndDate(moment(moment().format("YYYY-M-D")))
setCurrentPage(1)
} else if (val === "7 day") {
setStartDate(moment(moment().subtract(7, "days").format("YYYY-M-D")))
setEndDate(moment(moment().format("YYYY-M-D")))
setCurrentPage(1)
} else {
setStartDate(moment(moment().format("YYYY-M-D")))
setEndDate(moment(moment().format("YYYY-M-D")))
setCurrentPage(1)
}
}
return (
<div>
<NotificationContainer />
<DialogFoto
openDialog={openImage}
closeDialog={closeDialogImage}
toggleDialog={toggleDialogImage}
dataImage={dataImage}
/>
<Card>
<CardHeader style={{ display: "flex", justifyContent: "space-between" }}>
<h4 className="capitalize">{pageName}</h4>
<Row>
<Col>
<Tooltip title={t('exportExcel')}>
<Button style={{ marginLeft: "5px" }} id="TooltipExport" color="primary" onClick={() => handleExportExcel()}><i className="fa fa-print"></i></Button>
</Tooltip>
</Col>
</Row>
</CardHeader>
<CardBody>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<div style={{ width: "100%", display: "flex", alignItems: "center" }}>
<div style={{ width: "100%", marginRight: "10px", maxWidth: "200px" }}>
<Input type="select" onChange={(e) => handleChangeDay(e)} defaultValue={currentDay}>
<option value="today">{t('today')}</option>
<option value="3 day">{t('3days')}</option>
<option value="7 day">{t('7days')}</option>
</Input>
</div>
<div style={{ width: "50%", marginTop: "3px" }}>
<RangePicker format="DD-MM-YYYY" size="default" allowClear={false} value={[startDate, endDate]} onChange={handleDatePicker} />{' '}
<Button color="primary" onClick={() => getDataPresence()}>{t('search')}</Button>
</div>
</div>
<Input onChange={handleSearch} value={search} type="text" name="search" id="search" placeholder={t('searchHR')} style={{ maxWidth: "200px", marginBottom: "20px" }} />
</div>
{renderTable}
<Pagination
style={{ marginTop: "25px" }}
showSizeChanger
onShowSizeChange={onShowSizeChange}
onChange={onPagination}
current={currentPage}
pageSize={rowsPerPage}
total={totalPage}
pageSizeOptions={["10", "15", "20", "25", "30", "35", "40"]}
/>
</CardBody>
</Card>
</div>
)
}
export default Index;
import React, { useState, useEffect, useMemo } from 'react';
import { Card, CardBody, CardHeader, Col, Row, Input } from 'reactstrap';
import { Button } from 'reactstrap';
import axios from 'axios';
import * as XLSX from 'xlsx';
import { NotificationContainer, NotificationManager } from 'react-notifications';
import { Pagination, Tooltip, Table, DatePicker } from 'antd';
import moment from 'moment';
import { PRESENCE_SEARCH, IMAGE_GET_BY_ID } from '../../../const/ApiConst.js';
import DialogFoto from './DialogFoto';
import { useTranslation } from 'react-i18next';
const { RangePicker } = DatePicker;
const Index = ({ params,...props }) => {
let role_id = 0, user_id = 0, isLogin = false, token = '', company_id = 0, all_project = null, role_name='', hierarchy=[], user_name='';
if (props && props.role_id && props.user_id) {
role_id = props.role_id;
user_id = props.user_id;
token = props.token;
isLogin = props.isLogin;
company_id = props.company_id;
all_project = props.all_project;
role_name = props.role_name;
isLogin = props.isLogin;
hierarchy = props.hierarchy;
user_name = props.user_name;
}
const [dataTable, setDatatable] = useState([])
const [search, setSearch] = useState('')
const [currentPage, setCurrentPage] = useState(1)
const [totalPage, setTotalPage] = useState(0)
const [rowsPerPage, setRowsPerPage] = useState(10)
const [dataExport, setDataExport] = useState([])
const [startDate, setStartDate] = useState(moment(moment().format("YYYY-M-D")))
const [endDate, setEndDate] = useState(moment(moment().format("YYYY-M-D")))
const [currentDay, setCurrentDay] = useState("today")
const [dataImage, setDataImage] = useState(null)
const [openImage, setOpenImage] = useState(false)
const { t } = useTranslation()
const pageName = params.name;
const config = {
headers:
{
Authorization: `Bearer ${token}`,
"Content-type": `application/json`
}
};
useEffect(() => {
getDataPresence();
}, [search, currentPage, rowsPerPage, startDate, endDate])
useEffect(() => {
const cekData = dataExport || []
if (cekData.length > 0) {
exportExcel()
}
}, [dataExport])
const handleSearch = e => {
const value = e.target.value
setSearch(value);
setCurrentPage(1)
};
const getDataPresence = async () => {
let start = 0;
if (currentPage !== 1 && currentPage > 1) {
start = (currentPage * rowsPerPage) - rowsPerPage
}
let dateStart = moment(startDate).format("YYYY-MM-DD 00:00:00");
let dateEnd = moment(endDate).format("YYYY-MM-DD 23:59:59");
const payload = {
"paging": { "start": start, "length": rowsPerPage },
"columns": [
{ "name": "name", "logic_operator": "ilike", "value": search, "table_name": "m_users" },
{ "name": "clock_in", "logic_operator": "range", "value": dateStart, "value1": dateEnd },
],
"joins": [{
"name": "m_users",
"column_join": "user_id",
"column_results": [
"name",
"ktp_number"
]
}],
"orders": { "columns": ["id"], "ascending": false }
}
const result = await axios
.post(PRESENCE_SEARCH, payload, config)
.then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.code == 200) {
setDatatable(result.data.data);
setTotalPage(result.data.totalRecord);
} else {
NotificationManager.error('Gagal Mengambil Data!!', 'Failed');
}
}
const handleImage = async (id, name) => {
let url = IMAGE_GET_BY_ID(id, "presensi");
const result = await axios
.get(url, config)
.then(res => res)
.catch((error) => error.response);
if (result && result.data.code == 200) {
let dataRes = result.data.data
let dataImage = {
name,
url: dataRes.image
}
await setDataImage(dataImage)
setOpenImage(true)
} else {
NotificationManager.error('Data image tidak ditemukan!', 'Failed');
}
}
const closeDialogImage = () => {
setOpenImage(false)
setDataImage(null)
}
const toggleDialogImage = () => {
if (openImage) {
setDataImage(null)
}
setOpenImage(!openImage)
}
const onShowSizeChange = (current, pageSize) => {
setRowsPerPage(pageSize)
}
const onPagination = (current, pageSize) => {
setCurrentPage(current)
}
const renderDurasiKerja = (jamMasuk, jamKeluar) => {
if (jamMasuk && jamKeluar) {
let start = moment(jamMasuk),
end = moment(jamKeluar);
let diff = end.diff(start);
let result = moment.utc(diff).format('HH:mm:ss');
if (result) {
return result;
} else {
return "-"
}
} else {
return "-"
}
}
const handleExportExcel = async () => {
let dateStart = moment(startDate).format("YYYY-MM-DD 00:00:00");
let dateEnd = moment(endDate).format("YYYY-MM-DD 23:59:59");
const payload = {
"paging": { "start": 0, "length": -1 },
"columns": [
{ "name": "name", "logic_operator": "ilike", "value": search, "table_name": "m_users" },
{ "name": "clock_in", "logic_operator": "range", "value": dateStart, "value1": dateEnd },
],
"joins": [{
"name": "m_users",
"column_join": "user_id",
"column_results": [
"name",
"ktp_number"
]
}],
"orders": { "columns": ["id"], "ascending": false }
}
const result = await axios
.post(PRESENCE_SEARCH, payload, config)
.then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.code == 200) {
let resData = result.data.data;
const excelData = [];
resData.map((val, index) => {
let dataRow = {
"NIK/ID Card": val.join_first_ktp_number ? val.join_first_ktp_number : '-',
"Nama Human Resource": val.join_first_name ? val.join_first_name : '',
"Jam Masuk": val.clock_in ? moment(val.clock_in).format("D-M-YYYY HH:mm:ss") : '-',
"Jam Keluar": val.clock_out ? moment(val.clock_out).format("D-M-YYYY HH:mm:ss") : '-',
"Durasi Kerja": renderDurasiKerja(val.clock_in, val.clock_out),
"Lokasi Masuk": val.clock_in_loc && val.clock_in_loc !== '' ? val.clock_in_loc : '-',
"Lokasi Pulang": val.clock_out_loc && val.clock_out_loc !== '' ? val.clock_out_loc : '-',
"Area Kerja In": val.clock_in_boundary ? "Sesuai" : "Tidak Sesuai",
"Area Kerja Out": val.clock_out_boundary == null ? "-" : val.clock_out_boundary ? "Sesuai" : "Tidak Sesuai",
}
excelData.push(dataRow)
})
await setDataExport(excelData);
} else {
NotificationManager.error('Gagal Export Data!!', 'Failed');
}
}
const exportExcel = () => {
const dataExcel = dataExport || [];
const fileName = `Data ${pageName}.xlsx`;
const ws = XLSX.utils.json_to_sheet(dataExcel);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, `Data ${pageName}`);
XLSX.writeFile(wb, fileName);
setDataExport([])
}
const renderTable = useMemo(() => {
const columns = [
{
title: 'Action',
dataIndex: '',
key: 'x',
render: (text, record) => <>
<Tooltip title={t('image')}>
<i id="TooltipEdit" className="fa fa-image" style={{ color: 'green', cursor: "pointer" }} onClick={() => handleImage(text.id, text.join_first_name)}></i>
</Tooltip>
</>,
},
{ title: t('nik'), dataIndex: 'join_first_ktp_number', key: 'join_first_ktp_number' },
{ title: t('nameHR'), dataIndex: 'join_first_name', key: 'join_first_name' },
{ title: t('presenceIn'), dataIndex: 'clock_in', key: 'clock_in', render: (text, record) => (<div style={{ whiteSpace: "nowrap" }}>{text ? moment(text).format("D-M-YYYY HH:mm:ss") : "-"}</div>) },
{ title: t('presenceOut'), dataIndex: 'clock_out', key: 'clock_out', render: (text, record) => (<div style={{ whiteSpace: "nowrap" }}>{text ? moment(text).format("D-M-YYYY HH:mm:ss") : "-"}</div>) },
{ title: t('workDuration'), render: (text, record) => (<div style={{ whiteSpace: "nowrap" }}>{renderDurasiKerja(record.clock_in, record.clock_out)}</div>) },
{ title: t('locIn'), dataIndex: 'clock_in_loc', key: 'clock_in_loc', render: (text, record) => <>{text && text !== '' ? text : '-'}</> },
{ title: t('locOut'), dataIndex: 'clock_out_loc', key: 'clock_out_loc', render: (text, record) => <>{text && text !== '' ? text : '-'}</> },
{ title: t('workAreaIn'), dataIndex: 'clock_out_loc', key: 'clock_out_loc', render: (text, record) => (<div style={{ whiteSpace: "nowrap", textAlign: "center" }}>{record.clock_in_boundary ? <i className="fa fa-check-circle fa-lg" style={{ color: 'green' }}></i> : <i className="fa fa-times-circle fa-lg" style={{ color: 'red' }}></i>}</div>) },
{ title: t('workAreaOut'), dataIndex: 'clock_out_loc', key: 'clock_out_loc', render: (text, record) => (<div style={{ whiteSpace: "nowrap", textAlign: "center" }}>{record.clock_out_boundary == null ? <i class="fa fa-window-minimize fa-lg" style={{ color: 'orange' }}></i> : record.clock_out_boundary ? <i className="fa fa-check-circle fa-lg" style={{ color: 'green' }}></i> : <i className="fa fa-times-circle fa-lg" style={{ color: 'red' }}></i>}</div>) },
];
return (
<Table
rowKey="id"
size="small"
columns={columns}
dataSource={dataTable}
pagination={false}
/>
)
}, [dataTable])
const handleDatePicker = (date, dateString) => {
setStartDate(date[0])
setEndDate(date[1])
}
const handleChangeDay = (e) => {
const val = e.target.value;
setCurrentDay(val)
if (val === "today") {
setStartDate(moment(moment().format("YYYY-M-D")))
setEndDate(moment(moment().format("YYYY-M-D")))
setCurrentPage(1)
} else if (val === "3 day") {
setStartDate(moment(moment().subtract(3, "days").format("YYYY-M-D")))
setEndDate(moment(moment().format("YYYY-M-D")))
setCurrentPage(1)
} else if (val === "7 day") {
setStartDate(moment(moment().subtract(7, "days").format("YYYY-M-D")))
setEndDate(moment(moment().format("YYYY-M-D")))
setCurrentPage(1)
} else {
setStartDate(moment(moment().format("YYYY-M-D")))
setEndDate(moment(moment().format("YYYY-M-D")))
setCurrentPage(1)
}
}
return (
<div>
<NotificationContainer />
<DialogFoto
openDialog={openImage}
closeDialog={closeDialogImage}
toggleDialog={toggleDialogImage}
dataImage={dataImage}
/>
<Card>
<CardHeader style={{ display: "flex", justifyContent: "space-between" }}>
<h4 className="capitalize">{pageName}</h4>
<Row>
<Col>
<Tooltip title={t('exportExcel')}>
<Button style={{ marginLeft: "5px" }} id="TooltipExport" color="primary" onClick={() => handleExportExcel()}><i className="fa fa-print"></i></Button>
</Tooltip>
</Col>
</Row>
</CardHeader>
<CardBody>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<div style={{ width: "100%", display: "flex", alignItems: "center" }}>
<div style={{ width: "100%", marginRight: "10px", maxWidth: "200px" }}>
<Input type="select" onChange={(e) => handleChangeDay(e)} defaultValue={currentDay}>
<option value="today">{t('today')}</option>
<option value="3 day">{t('3days')}</option>
<option value="7 day">{t('7days')}</option>
</Input>
</div>
<div style={{ width: "50%", marginTop: "3px" }}>
<RangePicker format="DD-MM-YYYY" size="default" allowClear={false} value={[startDate, endDate]} onChange={handleDatePicker} />{' '}
<Button color="primary" onClick={() => getDataPresence()}>{t('search')}</Button>
</div>
</div>
<Input onChange={handleSearch} value={search} type="text" name="search" id="search" placeholder={t('searchHR')} style={{ maxWidth: "200px", marginBottom: "20px" }} />
</div>
{renderTable}
<Pagination
style={{ marginTop: "25px" }}
showSizeChanger
onShowSizeChange={onShowSizeChange}
onChange={onPagination}
current={currentPage}
pageSize={rowsPerPage}
total={totalPage}
pageSizeOptions={["10", "15", "20", "25", "30", "35", "40"]}
/>
</CardBody>
</Card>
</div>
)
}
export default Index;

45
src/views/SimproV2/ResourceWorker/index.js

@ -230,7 +230,10 @@ const ResourceWorker = ({ params, ...props }) => {
} else {
payload.group_column.where.push(
{ "name": "company_id", "logic_operator": "is null", "value": "", "operator": "AND" },
)
);
payload.joins.push(
{ name: "m_company", column_join: "company_id", column_results: ["company_name"] }
);
}
const result = await axios
@ -352,6 +355,19 @@ const ResourceWorker = ({ params, ...props }) => {
"ascending": false
}
}
if (role_name !== "Super Admin") {
payload.group_column.where.push(
{ "name": "company_id", "logic_operator": "=", "value": company_id, "operator": "AND" },
)
} else {
payload.group_column.where.push(
{ "name": "company_id", "logic_operator": "is null", "value": "", "operator": "AND" },
);
payload.joins.push(
{ name: "m_company", column_join: "company_id", column_results: ["company_name"] }
);
}
const result = await axios
.post(USER_SEARCH, payload, HEADER)
.then(res => res)
@ -361,14 +377,16 @@ const ResourceWorker = ({ params, ...props }) => {
let resData = result.data.data;
const excelData = [];
resData.map((n, index) => {
let dataRow = {
"NIK (Nomor Induk Karyawan)": n.ktp_number,
"Employee Name": n.name,
"Divisi": n.join_second_name,
"Employee Type": n.employee_type,
"Role": n.join_first_name,
"Phone No": n.phone_number,
let dataRow = {};
if (role_name === 'Super Admin') {
dataRow.Company = n.join_third_company_name;
}
dataRow["NIK (Nomor Induk Karyawan)"] = n.ktp_number;
dataRow["Employee Name"] = n.name;
dataRow["Divisi"] = n.join_second_name;
dataRow["Employee Type"] = n.employee_type;
dataRow.Role = n.join_first_name;
dataRow["Phone No"] = n.phone_number;
excelData.push(dataRow)
})
await setDataExport(excelData);
@ -521,7 +539,16 @@ const ResourceWorker = ({ params, ...props }) => {
</Tooltip>
</>,
},
{
title: role_name === 'Super Admin' ? "Company Name" : null,
dataIndex: "join_third_company_name",
key: "join_third_company_name",
render: (text, record) => {
return role_name === 'Super Admin' ? (
<span>{record.join_third_company_name}</span>
) : null;
}
},
{ title: t('nik'), dataIndex: 'ktp_number', key: 'ktp_number' },
{ title: t('nameHR'), dataIndex: 'name', key: 'name' },
{ title: t('division'), dataIndex: 'join_second_name', key: 'join_second_name' },

Loading…
Cancel
Save