root 1 year ago
parent
commit
e86f3a9145
  1. BIN
      docs/WhatsApp Image 2022-07-07 at 11.53.46 AM.jpeg
  2. 44
      src/assets/img/brand/logo.svg
  3. BIN
      src/assets/img/brand/logo_bmd_denpasar.png
  4. BIN
      src/assets/img/brand/logo_kominfo.jpeg
  5. BIN
      src/assets/img/brand/logo_siopas.png
  6. BIN
      src/assets/img/brand/logo_siopas_old.png
  7. 17
      src/assets/img/brand/sygnet.svg
  8. BIN
      src/assets/img/logo-surveyor-indonesia-2.png
  9. BIN
      src/assets/img/logo-surveyor-indonesia.png
  10. BIN
      src/assets/img/logo_adyawinsa.jpg
  11. BIN
      src/assets/img/logo_kit.png
  12. BIN
      src/assets/img/logo_nawakara.png
  13. BIN
      src/assets/img/yokke.png
  14. 152
      src/components/MapHeader/MapHeader.js
  15. 246
      src/components/PopupContainer/PopupContainer.js
  16. 3
      src/const/en.json
  17. 12
      src/containers/DefaultLayout/DefaultHeader.js
  18. 101
      src/dummy_data/paxel.geojson
  19. 7
      src/dummy_data/route.json
  20. 257
      src/dummy_data/route2.json
  21. 259
      src/dummy_data/route3.geojson
  22. 85
      src/dummy_data/sales.geojson
  23. 12
      src/views/Dashboard/DashboardBOD.js
  24. 1698
      src/views/Dashboard/DashboardProject.js.save
  25. 1698
      src/views/Dashboard/DashboardProject.js.save.1
  26. 37
      src/views/DashboardProject/chatDashboard.js
  27. 34
      src/views/DashboardProject/ganttDashboard.js
  28. 275
      src/views/DashboardProject/index.js
  29. 37
      src/views/DashboardProject/progressBar.js
  30. 72
      src/views/DashboardProject/tableDashboard.js
  31. 719
      src/views/Map/Map.js
  32. 0
      src/views/Master/MasterCountry/MasterCountry.css
  33. 51
      src/views/Master/MasterCountry/MasterCountry.js
  34. 6
      src/views/Master/MasterCountry/package.json
  35. 156
      src/views/Master/MasterGroupSales/DialogForm.js
  36. 291
      src/views/Master/MasterGroupSales/index.js
  37. 581
      src/views/Master/MasterKaryawan/DialogForm.js
  38. 79
      src/views/Master/MasterKaryawan/DialogImport.js
  39. 607
      src/views/Master/MasterKaryawan/index.js
  40. 262
      src/views/Master/MasterSales/DialogForm.js
  41. 347
      src/views/Master/MasterSales/SettingSales.js
  42. 399
      src/views/Master/MasterSales/index.js
  43. 0
      src/views/Master/MasterSubdistrict/MasterSubdistrict.css
  44. 50
      src/views/Master/MasterSubdistrict/MasterSubdistrict.js
  45. 6
      src/views/Master/MasterSubdistrict/package.json
  46. 0
      src/views/Master/MasterVillage/MasterVillage.css
  47. 50
      src/views/Master/MasterVillage/MasterVillage.js
  48. 6
      src/views/Master/MasterVillage/package.json
  49. 106
      src/views/Master/PlanningVsRealisasi/DialogEdit.js
  50. 85
      src/views/Master/PlanningVsRealisasi/DialogForm.js
  51. 104
      src/views/Master/PlanningVsRealisasi/DialogView.js
  52. 83
      src/views/Master/PlanningVsRealisasi/Map.js
  53. 608
      src/views/Master/PlanningVsRealisasi/index.js
  54. 211
      src/views/Master/UserWaspang/DialogForm.js
  55. 156
      src/views/Master/UserWaspang/DialogProyek.js
  56. 686
      src/views/Master/UserWaspang/index.js
  57. 17
      src/views/Pages/Login/Login.js
  58. 1
      src/views/SimproV2/CreatedProyek/AsignHrProject.js
  59. 25
      src/views/SimproV2/CreatedProyek/DialogFormGantt.js
  60. 15
      src/views/SimproV2/CreatedProyek/DialogGantt.js
  61. 12
      src/views/SimproV2/CreatedProyek/index.js
  62. 2
      src/views/SimproV2/ResourceWorker/DialogForm.js

BIN
docs/WhatsApp Image 2022-07-07 at 11.53.46 AM.jpeg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

44
src/assets/img/brand/logo.svg

@ -1,44 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Warstwa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="707.1px" height="200px" viewBox="0 0 707.1 200" enable-background="new 0 0 707.1 200" xml:space="preserve">
<polygon fill="#61DAFB" points="0,150 0,50 86.6,0 173.2,50 173.2,150 86.6,200 "/>
<polygon fill="#FFFFFF" points="86.6,133.3 57.7,116.7 57.7,83.3 86.6,66.7 115.5,83.3 144.3,66.7 86.6,33.3 28.9,66.7 28.9,133.3
86.6,166.7 144.3,133.3 115.5,116.7 "/>
<polygon opacity="0.04" stroke="#FFFFFF" stroke-miterlimit="10" enable-background="new " points="0,50 86.6,100 86.6,0 "/>
<polygon opacity="0.04" stroke="#FFFFFF" stroke-miterlimit="10" enable-background="new " points="0,150 86.6,200 86.6,100 "/>
<polygon opacity="0.08" stroke="#FFFFFF" stroke-miterlimit="10" enable-background="new " points="86.6,100 173.2,150 173.2,50
"/>
<polygon fill-opacity="0" points="86.6,100 0,50 0,150 "/>
<polygon opacity="0.08" stroke="#FFFFFF" stroke-miterlimit="10" enable-background="new " points="173.2,150 86.6,100 86.6,200
"/>
<polygon opacity="0.08" stroke="#FFFFFF" stroke-miterlimit="10" enable-background="new " points="173.2,50 86.6,0 86.6,100 "/>
<g>
<path fill="#333333" d="M290.4,127.3c1,0,1.8,0.4,2.6,1.1l7.2,7.8c-4,4.9-8.8,8.7-14.6,11.3c-5.8,2.6-12.7,3.9-20.8,3.9
c-7.2,0-13.8-1.2-19.5-3.7c-5.8-2.5-10.7-5.9-14.8-10.3c-4.1-4.4-7.2-9.7-9.4-15.8c-2.2-6.1-3.3-12.8-3.3-20
c0-7.3,1.2-14.1,3.6-20.1c2.4-6.1,5.8-11.4,10.3-15.8c4.4-4.4,9.7-7.8,15.8-10.3s12.9-3.7,20.4-3.7c7.2,0,13.6,1.2,19,3.5
s10.1,5.4,13.9,9.2l-6.1,8.4c-0.4,0.5-0.8,1-1.4,1.4s-1.3,0.6-2.3,0.6s-2.1-0.4-3.2-1.2s-2.5-1.7-4.1-2.6c-1.7-0.9-3.8-1.8-6.3-2.6
c-2.5-0.8-5.8-1.2-9.7-1.2c-4.6,0-8.8,0.8-12.7,2.4c-3.8,1.6-7.2,3.9-9.9,6.9s-4.9,6.6-6.5,10.8c-1.6,4.3-2.3,9-2.3,14.3
c0,5.5,0.8,10.4,2.3,14.6c1.6,4.3,3.7,7.9,6.3,10.8c2.7,2.9,5.8,5.2,9.4,6.7c3.6,1.6,7.5,2.3,11.6,2.3c2.5,0,4.7-0.1,6.7-0.4
c2-0.3,3.8-0.7,5.5-1.3s3.3-1.3,4.8-2.3c1.5-0.9,3-2.1,4.5-3.4c0.4-0.4,0.9-0.7,1.4-1C289.3,127.4,289.9,127.3,290.4,127.3z"/>
<path fill="#333333" d="M407.5,101.5c0,7.2-1.2,13.8-3.6,19.9s-5.7,11.4-10.1,15.8c-4.3,4.5-9.5,7.9-15.6,10.4s-12.8,3.7-20.2,3.7
c-7.4,0-14.1-1.2-20.2-3.7s-11.3-6-15.7-10.4c-4.3-4.5-7.7-9.7-10.1-15.8c-2.4-6.1-3.6-12.7-3.6-19.9c0-7.2,1.2-13.8,3.6-19.9
s5.7-11.4,10.1-15.8c4.3-4.5,9.6-7.9,15.7-10.4s12.8-3.7,20.2-3.7c7.4,0,14.1,1.3,20.2,3.8s11.3,6,15.6,10.4
c4.3,4.4,7.7,9.7,10.1,15.8C406.3,87.7,407.5,94.3,407.5,101.5z M388.9,101.5c0-5.4-0.7-10.2-2.1-14.4c-1.4-4.3-3.5-7.9-6.1-10.8
c-2.7-3-5.9-5.2-9.7-6.8c-3.8-1.6-8.1-2.4-12.9-2.4s-9.1,0.8-12.9,2.4s-7.1,3.8-9.8,6.8c-2.7,3-4.7,6.6-6.2,10.8
c-1.4,4.3-2.2,9.1-2.2,14.4c0,5.4,0.7,10.2,2.2,14.4c1.4,4.3,3.5,7.9,6.2,10.8s5.9,5.2,9.8,6.8c3.8,1.6,8.1,2.4,12.9,2.4
s9.1-0.8,12.9-2.4c3.8-1.6,7-3.8,9.7-6.8c2.7-2.9,4.7-6.5,6.1-10.8C388.2,111.7,388.9,106.9,388.9,101.5z"/>
<path fill="#333333" d="M440.6,112.2v38.1h-18.2V52.7h29.8c6.7,0,12.4,0.7,17.1,2.1c4.7,1.4,8.6,3.3,11.7,5.8
c3,2.5,5.3,5.4,6.7,8.9c1.4,3.4,2.1,7.2,2.1,11.4c0,3.3-0.5,6.4-1.5,9.3s-2.4,5.6-4.2,8c-1.8,2.4-4.1,4.5-6.8,6.3
c-2.7,1.8-5.7,3.2-9.1,4.3c2.3,1.3,4.3,3.2,5.9,5.6l24.4,36h-16.3c-1.6,0-2.9-0.3-4-0.9c-1.1-0.6-2-1.5-2.8-2.7l-20.5-31.3
c-0.8-1.2-1.6-2-2.5-2.5s-2.3-0.7-4.1-0.7h-7.7V112.2z M440.6,99.1h11.3c3.4,0,6.4-0.4,8.9-1.3s4.6-2,6.3-3.5
c1.6-1.5,2.9-3.3,3.7-5.4c0.8-2.1,1.2-4.3,1.2-6.8c0-4.9-1.6-8.8-4.9-11.4c-3.3-2.7-8.2-4-15-4h-11.6v32.4H440.6z"/>
<path fill="#333333" d="M571.8,52.7v14.4h-43.3v27.1h34.1v14h-34.1v27.6h43.3v14.5h-61.6V52.7H571.8z"/>
<path fill="#61DAFB" d="M626.8,135.7c3.5,0,6.6-0.6,9.4-1.8c2.8-1.2,5.1-2.8,7-4.9c1.9-2.1,3.4-4.7,4.4-7.7s1.5-6.4,1.5-10.1V52.7
h18.2v58.5c0,5.8-0.9,11.2-2.8,16.1c-1.9,4.9-4.6,9.2-8.1,12.8c-3.5,3.6-7.8,6.4-12.8,8.4s-10.6,3-16.9,3s-11.9-1-16.9-3
s-9.2-4.8-12.7-8.4c-3.5-3.6-6.2-7.8-8-12.8c-1.9-4.9-2.8-10.3-2.8-16.1V52.7h18.2v58.4c0,3.7,0.5,7.1,1.5,10.1s2.5,5.6,4.4,7.7
s4.2,3.8,7,5C620.1,135.1,623.3,135.7,626.8,135.7z"/>
<path fill="#61DAFB" d="M706.2,150.3H688V52.7h18.2V150.3z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.2 KiB

BIN
src/assets/img/brand/logo_bmd_denpasar.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

BIN
src/assets/img/brand/logo_kominfo.jpeg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

BIN
src/assets/img/brand/logo_siopas.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

BIN
src/assets/img/brand/logo_siopas_old.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

17
src/assets/img/brand/sygnet.svg

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Warstwa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="173.2px" height="200px" viewBox="0 0 173.2 200" enable-background="new 0 0 173.2 200" xml:space="preserve">
<polygon fill="#61DAFB" points="0,150 0,50 86.6,0 173.2,50 173.2,150 86.6,200 "/>
<polygon fill="#FFFFFF" points="86.6,133.3 57.7,116.7 57.7,83.3 86.6,66.7 115.5,83.3 144.3,66.7 86.6,33.3 28.9,66.7 28.9,133.3
86.6,166.7 144.3,133.3 115.5,116.7 "/>
<polygon opacity="0.04" stroke="#FFFFFF" stroke-miterlimit="10" enable-background="new " points="0,50 86.6,100 86.6,0 "/>
<polygon opacity="0.04" stroke="#FFFFFF" stroke-miterlimit="10" enable-background="new " points="0,150 86.6,200 86.6,100 "/>
<polygon opacity="0.08" stroke="#FFFFFF" stroke-miterlimit="10" enable-background="new " points="86.6,100 173.2,150 173.2,50
"/>
<polygon fill-opacity="0" points="86.6,100 0,50 0,150 "/>
<polygon opacity="0.08" stroke="#FFFFFF" stroke-miterlimit="10" enable-background="new " points="173.2,150 86.6,100 86.6,200
"/>
<polygon opacity="0.08" stroke="#FFFFFF" stroke-miterlimit="10" enable-background="new " points="173.2,50 86.6,0 86.6,100 "/>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/assets/img/logo-surveyor-indonesia-2.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

BIN
src/assets/img/logo-surveyor-indonesia.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 KiB

BIN
src/assets/img/logo_adyawinsa.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

BIN
src/assets/img/logo_kit.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

BIN
src/assets/img/logo_nawakara.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 KiB

BIN
src/assets/img/yokke.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 328 KiB

152
src/components/MapHeader/MapHeader.js

@ -1,20 +1,16 @@
import React, { Component } from 'react';
import { Link, NavLink } from 'react-router-dom';
import { Badge, UncontrolledDropdown, DropdownItem, DropdownMenu, DropdownToggle, Nav, NavItem,
InputGroup, Input, InputGroupAddon, InputGroupText, Button, UncontrolledTooltip
import { NavLink } from 'react-router-dom';
import {
UncontrolledDropdown, DropdownItem, DropdownMenu, DropdownToggle, Nav, NavItem,
UncontrolledTooltip
} from 'reactstrap';
import PropTypes from 'prop-types';
import { AppAsideToggler, AppNavbarBrand, AppSidebarToggler } from '@coreui/react';
import logo from '../../assets/img/brand/logo_siopas.png'
import logo_bmd_denpasar from '../../assets/img/brand/logo_bmd_denpasar.png'
import user_logo from '../../assets/img/avatars/user.png'
import sygnet from '../../assets/img/brand/sygnet.svg'
import { Icon, InlineIcon } from '@iconify/react';
import saveOutline from '@iconify/icons-ion/save-outline';
import { Icon } from '@iconify/react';
import printOutline from '@iconify/icons-ion/print-outline';
import {
AppHeader
AppHeader
} from '@coreui/react';
import {
mappify,
@ -23,7 +19,7 @@ import {
import { nominatimBaseUrl } from '../../const/MapConst';
const propTypes = {
children: PropTypes.node,
children: PropTypes.node,
};
const defaultProps = {};
@ -31,71 +27,71 @@ const defaultProps = {};
class MapHeader extends Component {
getHeaderMenu = () => {
let u_group = localStorage.getItem('u_group');
if (u_group == 'kominfo') {
return (
<NavItem className="px-3">
<NavLink to="/dashboard-kominfo" className="nav-link" >Dashboard</NavLink>
</NavItem>
)
}
else {
return (
<NavItem className="px-3">
<NavLink to="/dashboard" className="nav-link" >Dashboard</NavLink>
</NavItem>
)
}
}
getLogo = () => {
return (
<div style={{fontWeight: 'bold', fontSize: 30, fontFamily: 'Calibri, Candara, Segoe, "Segoe UI", Optima, Arial, sans-serif', textAlign: 'center', marginLeft: 25, marginRight: 20}}>
<span style={{color: '#4472C4'}}>OS</span><span style={{color: '#ED7D31'}}>PRO</span>
</div>
)
}
getHeaderMenu = () => {
let u_group = localStorage.getItem('u_group');
if (u_group == 'kominfo') {
return (
<NavItem className="px-3">
<NavLink to="/dashboard-kominfo" className="nav-link" >Dashboard</NavLink>
</NavItem>
)
}
else {
return (
<NavItem className="px-3">
<NavLink to="/dashboard" className="nav-link" >Dashboard</NavLink>
</NavItem>
)
}
}
getLogo = () => {
return (
<div style={{ fontWeight: 'bold', fontSize: 30, fontFamily: 'Calibri, Candara, Segoe, "Segoe UI", Optima, Arial, sans-serif', textAlign: 'center', marginLeft: 25, marginRight: 20 }}>
<span style={{ color: '#4472C4' }}>OS</span><span style={{ color: '#ED7D31' }}>PRO</span>
</div>
)
}
render() {
const { children, ...attributes } = this.props;
const { children, ...attributes } = this.props;
return (
<AppHeader fixed>
{/*<AppNavbarBrand
return (
<AppHeader fixed>
{/*<AppNavbarBrand
full={{ src: logo, width: 89, height: 35, alt: 'SIOPAS Logo' }}
minimized={{ src: logo, width: 30, height: 35, alt: 'SIOPAS Logo' }}
/>*/}
{ this.getLogo() }
{this.getLogo()}
<Nav className="d-md-down-none" navbar>
{ this.getHeaderMenu() }
</Nav>
<Nav className="ml-auto" navbar>
{/*<InputGroup>
<Nav className="d-md-down-none" navbar>
{this.getHeaderMenu()}
</Nav>
<Nav className="ml-auto" navbar>
{/*<InputGroup>
<Input placeholder="Search Address" />
<InputGroupAddon addonType="append">
<Button color="secondary"><i className="fa fa-search" style={{color: '#ffffff'}}></i></Button>
</InputGroupAddon>
</InputGroup>*/}
<NominatimSearch
map={this.props.olmap}
placeholder="Search Address"
nominatimBaseUrl={nominatimBaseUrl}
countrycodes="id"
/>
{/*<NavItem className="d-md-down-none">
<NominatimSearch
map={this.props.olmap}
placeholder="Search Address"
nominatimBaseUrl={nominatimBaseUrl}
countrycodes="id"
/>
{/*<NavItem className="d-md-down-none">
<NavLink to="#" className="nav-link"><i className="icon-bell"></i><Badge pill color="danger">5</Badge></NavLink>
</NavItem>*/}
{/*<NavItem className="d-md-down-none">
{/*<NavItem className="d-md-down-none">
<NavLink to="#" className="nav-link"><i className="icon-list"></i></NavLink>
</NavItem>*/}
{/*<NavItem className="d-md-down-none">
{/*<NavItem className="d-md-down-none">
<NavLink to="#" className="nav-link"><i className="icon-location-pin"></i></NavLink>
</NavItem>*/}
{/*<div>
{/*<div>
<NavItem className="d-md-down-none" id="saveMap">
<NavLink to="#" className="nav-link" onClick={() => this.props.saveMap()}><Icon icon={saveOutline} width={15} height={15} /></NavLink>
</NavItem>
@ -103,21 +99,21 @@ class MapHeader extends Component {
Save Map
</UncontrolledTooltip>
</div>*/}
<div>
<NavItem className="d-md-down-none" id="printMap">
<NavLink to="#" className="nav-link" onClick={() => this.props.printMap() }><Icon icon={printOutline} width={15} height={15} /></NavLink>
</NavItem>
<UncontrolledTooltip placement="bottom" target="printMap">
Print Map
</UncontrolledTooltip>
</div>
<UncontrolledDropdown nav direction="down">
<DropdownToggle nav>
<img src={user_logo} className="img-avatar" alt="admin@bootstrapmaster.com" />
</DropdownToggle>
<DropdownMenu right>
{/*<DropdownItem header tag="div" className="text-center"><strong>Account</strong></DropdownItem>
<div>
<NavItem className="d-md-down-none" id="printMap">
<NavLink to="#" className="nav-link" onClick={() => this.props.printMap()}><Icon icon={printOutline} width={15} height={15} /></NavLink>
</NavItem>
<UncontrolledTooltip placement="bottom" target="printMap">
Print Map
</UncontrolledTooltip>
</div>
<UncontrolledDropdown nav direction="down">
<DropdownToggle nav>
<img src={user_logo} className="img-avatar" alt="admin@bootstrapmaster.com" />
</DropdownToggle>
<DropdownMenu right>
{/*<DropdownItem header tag="div" className="text-center"><strong>Account</strong></DropdownItem>
<DropdownItem><i className="fa fa-bell-o"></i> Updates<Badge color="info">42</Badge></DropdownItem>
<DropdownItem><i className="fa fa-envelope-o"></i> Messages<Badge color="success">42</Badge></DropdownItem>
<DropdownItem><i className="fa fa-tasks"></i> Tasks<Badge color="danger">42</Badge></DropdownItem>
@ -129,13 +125,13 @@ class MapHeader extends Component {
<DropdownItem><i className="fa fa-file"></i> Projects<Badge color="primary">42</Badge></DropdownItem>
<DropdownItem divider />
<DropdownItem><i className="fa fa-shield"></i> Lock Account</DropdownItem>*/}
<DropdownItem header tag="div" className="text-center">{ localStorage.getItem('user_name') }</DropdownItem>
<DropdownItem onClick={e => this.props.onLogout(e)}><i className="fa fa-lock"></i> Logout</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
</Nav>
</AppHeader>
)
<DropdownItem header tag="div" className="text-center">{localStorage.getItem('user_name')}</DropdownItem>
<DropdownItem onClick={e => this.props.onLogout(e)}><i className="fa fa-lock"></i> Logout</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
</Nav>
</AppHeader>
)
}

246
src/components/PopupContainer/PopupContainer.js

@ -1,6 +1,6 @@
import React, { Component, Fragment } from 'react';
import {Vector as VectorLayer} from 'ol/layer';
import {Vector as VectorSource} from 'ol/source';
import { Vector as VectorLayer } from 'ol/layer';
import { Vector as VectorSource } from 'ol/source';
import Feature from 'ol/Feature';
import { Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon } from 'ol/geom';
import { Circle as CircleStyle, Fill, Icon as IconOl, Stroke, Style, Text } from 'ol/style';
@ -32,8 +32,8 @@ import axios from "axios"
import moment from "moment"
import { deleteFeature, getImagePopup, formatLength, formatArea, lightOrDark } from '../../const/GeoserverFunc.js';
import { formatLabel, hideAttr, dateColumns, DATE_TIME_FORMAT } from '../../const/CustomFunc.js'
import {API_UPLOAD_IMAGE, BASE_IMAGE, BASE_SIMPRO } from '../../const/ApiConst.js'
import routeDummy from '../../dummy_data/route2.json';
import { API_UPLOAD_IMAGE, BASE_IMAGE, BASE_SIMPRO } from '../../const/ApiConst.js'
class PopupContainer extends Component {
@ -53,7 +53,7 @@ class PopupContainer extends Component {
featureExtent: null,
mapProjection: this.props.olmap.getView().getProjection(),
fitOption: {
size: this.props.olmap.getSize(),
size: this.props.olmap.getSize(),
duration: 500,
maxZoom: 18
},
@ -69,7 +69,7 @@ class PopupContainer extends Component {
}
componentDidMount() {
this.setState({isReady: true});
this.setState({ isReady: true });
}
/*componentDidMount() {
@ -91,18 +91,18 @@ class PopupContainer extends Component {
matchLayerAttribute = (propKey) => {
const { layer_attribute } = this.props;
for (let i=0; i < layer_attribute.length; i++) {
for (let i = 0; i < layer_attribute.length; i++) {
if (layer_attribute[i].attribute !== 'the_geom') {
if (layer_attribute[i].attribute_label !== null && layer_attribute[i].attribute_label !== '' ) {
if (propKey == layer_attribute[i].attribute) {
return layer_attribute[i].attribute_label;
}
if (layer_attribute[i].attribute_label !== null && layer_attribute[i].attribute_label !== '') {
if (propKey == layer_attribute[i].attribute) {
return layer_attribute[i].attribute_label;
}
else {
if (propKey == layer_attribute[i].attribute) {
return layer_attribute[i].attribute;
}
}
else {
if (propKey == layer_attribute[i].attribute) {
return layer_attribute[i].attribute;
}
}
}
}
}
@ -142,7 +142,7 @@ class PopupContainer extends Component {
else {
return "";
}
}
getLayerColor = (item) => {
@ -234,18 +234,18 @@ class PopupContainer extends Component {
</div>
{/*<div className="image-slider" onClick={() => this.showImageFeature(selectedPopupData)}>*/}
<div className="image-popup-container">
{ this.renderImageSlider(selectedPopupData) }
{this.renderImageSlider(selectedPopupData)}
</div>
<div className="popup-body custom-scroll">
<table className="table popup-table">
<tbody>
{ this.renderOneRowFeature(popupProperties) }
{this.renderOneRowFeature(popupProperties)}
</tbody>
</table>
</div>
<div className="popup-footer">
<div className="btn-group">
{ this.renderButtonFooter(selectedPopupData) }
{this.renderButtonFooter(selectedPopupData)}
</div>
</div>
</div>
@ -261,7 +261,7 @@ class PopupContainer extends Component {
for (let key in popupProperties) {
if (typeof(popupProperties[key]) === 'object') {
if (typeof (popupProperties[key]) === 'object') {
for (let prop in popupProperties[key]) {
modPopupProperties[prop] = popupProperties[key][prop];
}
@ -271,7 +271,7 @@ class PopupContainer extends Component {
}
for (let key in modPopupProperties) {
if (typeof(modPopupProperties[key]) === 'object') {
if (typeof (modPopupProperties[key]) === 'object') {
delete modPopupProperties[key];
}
}
@ -293,7 +293,7 @@ class PopupContainer extends Component {
const row = [];
for (let key in popupProperties) {
let propKey = this.matchLayerAttribute(key);
if (propKey !== undefined) {
@ -310,7 +310,7 @@ class PopupContainer extends Component {
renderButtonFooter = (selectedPopupData) => {
let layer_name = selectedPopupData.id && selectedPopupData.id.substr(0, selectedPopupData.id.indexOf("."));
return(
return (
<Fragment>
<Button color="success" size="sm" outline onClick={() => this.showImageFeature(selectedPopupData)} id="showImageFeature">
<Icon icon={imageOutline} width={15} height={15} />
@ -336,13 +336,13 @@ class PopupContainer extends Component {
<UncontrolledTooltip placement="bottom" target="editFeature">
Edit Attribute
</UncontrolledTooltip>
{ this.props.activeStateAddGeometry ?
(<Button disabled color="success" size="sm" outline id="editGeometry">
<Icon icon={pencilIcon} width={15} height={15} />
</Button>) :
(<Button color="success" size="sm" outline onClick={() => this.editGeometry(selectedPopupData)} id="editGeometry">
<Icon icon={pencilIcon} width={15} height={15} />
</Button>)
{this.props.activeStateAddGeometry ?
(<Button disabled color="success" size="sm" outline id="editGeometry">
<Icon icon={pencilIcon} width={15} height={15} />
</Button>) :
(<Button color="success" size="sm" outline onClick={() => this.editGeometry(selectedPopupData)} id="editGeometry">
<Icon icon={pencilIcon} width={15} height={15} />
</Button>)
}
<UncontrolledTooltip placement="bottom" target="editGeometry">
Edit Geometry
@ -354,27 +354,27 @@ class PopupContainer extends Component {
Delete Feature
</UncontrolledTooltip>
{ layer_name && (layer_name === "m_sales" || layer_name === "m_employee" || layer_name === "m_waspang" || layer_name === "m_presensi") &&
<>
<Button color="success" size="sm" outline
onClick={() => {
let routeType = layer_name.split("_")[1];
this.props.toggleRoutingBarVisible()
this.props.setRouteType(routeType)
}}
id="showRoute">
<Icon icon={routeIcon} width={15} height={15} />
</Button>
<UncontrolledTooltip placement="bottom" target="showRoute">
Show Route
</UncontrolledTooltip>
</> }
{layer_name && (layer_name === "m_sales" || layer_name === "m_employee" || layer_name === "m_waspang" || layer_name === "m_presensi") &&
<>
<Button color="success" size="sm" outline
onClick={() => {
let routeType = layer_name.split("_")[1];
this.props.toggleRoutingBarVisible()
this.props.setRouteType(routeType)
}}
id="showRoute">
<Icon icon={routeIcon} width={15} height={15} />
</Button>
<UncontrolledTooltip placement="bottom" target="showRoute">
Show Route
</UncontrolledTooltip>
</>}
</Fragment>
)
}
renderImageSlider = (selectedPopupData) => {
if (this.props.popupDataTemp[0].id == selectedPopupData.id) {
if (this.props.popupDataTemp[0].id == selectedPopupData.id) {
return <ImageSlider id={selectedPopupData.id} />;
} else {
return <DefaultImageSlider />
@ -466,13 +466,13 @@ class PopupContainer extends Component {
<div className="popup-body custom-scroll">
<table className="table table-hover popup-table">
<tbody>
{ popupDataTemp.map((item, index) => {
return (<tr key={index} className="popup-row-list-feature"
{popupDataTemp.map((item, index) => {
return (<tr key={index} className="popup-row-list-feature"
onClick={() => this.chooseOneFeature(item)}>
<td>{this.getFeaturesLabel(item)}</td>
<td> <Badge style={{backgroundColor: this.getLayerColor(item)}} className={this.getLayerTitleTextColor(this.getLayerColor(item))}>{this.getLayerTitle(item)}</Badge> </td>
</tr>)
}) }
<td>{this.getFeaturesLabel(item)}</td>
<td> <Badge style={{ backgroundColor: this.getLayerColor(item) }} className={this.getLayerTitleTextColor(this.getLayerColor(item))}>{this.getLayerTitle(item)}</Badge> </td>
</tr>)
})}
</tbody>
</table>
</div>
@ -492,73 +492,73 @@ class PopupContainer extends Component {
showImageFeature = (selectedPopupData) => {
console.log('show images', selectedPopupData);
this.setState({imagePopupTitle: selectedPopupData.id});
this.setState({ imagePopupTitle: selectedPopupData.id });
this.toggleImagePopup();
}
getFrontPhotoLicense = event => {
this.setState({
photo_feature: event.target.files[0],
image_feature: URL.createObjectURL(event.target.files[0]),
imagePreviewVisible: true
photo_feature: event.target.files[0],
image_feature: URL.createObjectURL(event.target.files[0]),
imagePreviewVisible: true
})
}
toggleImagePopup = () => {
this.setState({imagePopupVisible: !this.state.imagePopupVisible});
this.setState({ imagePopupVisible: !this.state.imagePopupVisible });
}
handleUploadImage = async () => {
const {photo_feature, image_feature, imagePopupTitle} = this.state
const category = imagePopupTitle.split(".");
let type = category[0]
let id = category[1]
let imageType = ''
if(type==="m_office"){
imageType="office"
}else if(type==="m_sales"){
imageType="m_sales"
}else if(type==="m_employee"){
imageType="employee"
}else{
imageType="customer"
}
const formData = new FormData()
formData.append('ref_id', id)
formData.append('files', photo_feature)
let url = `${BASE_SIMPRO}/image/${imageType}/upload`;
const result = await axios.post(url, formData)
.then(res => res)
.catch((error) => error.response);
const { photo_feature, image_feature, imagePopupTitle } = this.state
const category = imagePopupTitle.split(".");
let type = category[0]
let id = category[1]
let imageType = ''
if (type === "m_office") {
imageType = "office"
} else if (type === "m_sales") {
imageType = "m_sales"
} else if (type === "m_employee") {
imageType = "employee"
} else {
imageType = "customer"
}
const formData = new FormData()
formData.append('ref_id', id)
formData.append('files', photo_feature)
let url = `${BASE_SIMPRO}/image/${imageType}/upload`;
const result = await axios.post(url, formData)
.then(res => res)
.catch((error) => error.response);
return result
return result
}
toggleImagePreview = async param => {
if(param == "upload"){
const result = await this.handleUploadImage()
console.log("response upload image",result);
if (result == undefined) {
alert('Upload Failed');
return;
if (param == "upload") {
const result = await this.handleUploadImage()
console.log("response upload image", result);
if (result == undefined) {
alert('Upload Failed');
return;
}
else {
if (result.data.code == 200) {
alert('Successfully uploaded image');
this.toggleImagePopup();
}
else {
if (result.data.code == 200) {
alert('Successfully uploaded image');
this.toggleImagePopup();
}
else {
console.log('err',result);
alert(result.data);
return;
}
console.log('err', result);
alert(result.data);
return;
}
}
}
this.setState({imagePreviewVisible: !this.state.imagePreviewVisible});
this.setState({ imagePreviewVisible: !this.state.imagePreviewVisible });
}
showTable = (selectedPopupData) => {
@ -566,16 +566,16 @@ class PopupContainer extends Component {
}
toggleShowTable = () => {
this.setState({mapTableVisible: !this.state.mapTableVisible})
this.setState({ mapTableVisible: !this.state.mapTableVisible })
}
editFeature = (selectedPopupData) => {
console.log('edit feature', selectedPopupData);
this.setState({selectedPopupData: selectedPopupData}, () => this.toggleEditFeature());
this.setState({ selectedPopupData: selectedPopupData }, () => this.toggleEditFeature());
}
toggleEditFeature = () => {
this.setState({editFeatureVisible: !this.state.editFeatureVisible})
this.setState({ editFeatureVisible: !this.state.editFeatureVisible })
}
/*goToFeature = (selectedPopupData) => {
@ -662,7 +662,7 @@ class PopupContainer extends Component {
}
toggleEditGeometry = () => {
this.setState({editGeometryVisible: !this.state.editGeometryVisible})
this.setState({ editGeometryVisible: !this.state.editGeometryVisible })
}
deleteFeature = async (selectedPopupData) => {
@ -707,38 +707,38 @@ class PopupContainer extends Component {
console.log('imageArr', imageArr);
}*/
render() {
let { isReady, alert, alertMessage, successAlert, dangerAlert } = this.state;
if (!isReady) {
return <div>Loading...</div>
}
return(
<div>
<SweetAlert show={alert} success={successAlert} danger={dangerAlert} title={alertMessage} onConfirm={() => this.setState({alert: false, successAler: false, dangerAlert: false})}>
return (
<div>
<SweetAlert show={alert} success={successAlert} danger={dangerAlert} title={alertMessage} onConfirm={() => this.setState({ alert: false, successAler: false, dangerAlert: false })}>
{alertMessage}
</SweetAlert>
{this.fillPopupContent()}
{
{
this.state.imagePopupVisible &&
<ImagePopup
uploadImagePopup={this.getFrontPhotoLicense}
imagePopupVisible={this.state.imagePopupVisible}
toggleImagePopup={() => this.toggleImagePopup()}
imagePopupTitle={this.state.imagePopupTitle ? this.state.imagePopupTitle : 'Feature Image'}
id={this.props.popupDataTemp[0].id}
/>
<ImagePopup
uploadImagePopup={this.getFrontPhotoLicense}
imagePopupVisible={this.state.imagePopupVisible}
toggleImagePopup={() => this.toggleImagePopup()}
imagePopupTitle={this.state.imagePopupTitle ? this.state.imagePopupTitle : 'Feature Image'}
id={this.props.popupDataTemp[0].id}
/>
}
{
{
this.state.imagePreviewVisible &&
<ImagePopupPreview
imageUrl={this.state.image_feature}
imagePopupVisible={this.state.imagePreviewVisible}
toggleImagePopup={this.toggleImagePreview}
imagePopupTitle={"Upload Photo"}
/>
<ImagePopupPreview
imageUrl={this.state.image_feature}
imagePopupVisible={this.state.imagePreviewVisible}
toggleImagePopup={this.toggleImagePreview}
imagePopupTitle={"Upload Photo"}
/>
}
{
this.state.editFeatureVisible &&
@ -772,10 +772,10 @@ class PopupContainer extends Component {
/>
}*/}
</div>
)
)
}
}

3
src/const/en.json

@ -46,6 +46,9 @@
"icon": "Icon",
"inputIcon": "Input Code Icon",
"inputName": "Input Name",
"inputaddress": "Input Address",
"inputBrithPlace": "Input Birth Place",
"inputBrithDate": "Select Birth Date",
"inputDescription": "Input Description",
"inputParentMenu": "Select Parent Menu",
"inputAliasMenu": "Input Menu Alias",

12
src/containers/DefaultLayout/DefaultHeader.js

@ -1,14 +1,10 @@
import React, { Component } from 'react';
import { Link, NavLink } from 'react-router-dom';
import { Badge, UncontrolledDropdown, DropdownItem, DropdownMenu, DropdownToggle, Nav, NavItem } from 'reactstrap';
import { NavLink } from 'react-router-dom';
import { Badge, Nav, NavItem } from 'reactstrap';
import PropTypes from 'prop-types';
import { Menu, Dropdown, Row, Col } from 'antd'
import { AppAsideToggler, AppNavbarBrand, AppSidebarToggler } from '@coreui/react';
import { Menu, Dropdown } from 'antd'
import { ALERTUSER_SEARCH, ALERT_SEARCH, ALERTUSER_STATUSVIEW, ALERT_STATUSVIEW, APP_MODE } from '../../const/ApiConst';
import user_logo from '../../assets/img/avatars/user.png'
import logo_header_adw from '../../assets/img/logo_adyawinsa.jpg'
import logo_header_kit from '../../assets/img/logo_kit.png'
import logo_header_nawakara from '../../assets/img/logo_nawakara.png'
import axios from 'axios';
import './Default.css'
const token = window.localStorage.getItem('token');

101
src/dummy_data/paxel.geojson

@ -1,101 +0,0 @@
{
"type": "FeatureCollection",
"totalFeatures": "unknown",
"features": [
{
"type": "Feature",
"id": "paxel_area_code_20210426.5083",
"geometry": {
"type": "MultiPolygon",
"coordinates": [
[
[
[
106.522270001261,
-6.66321000044036
],
[
106.536260000699,
-6.66382999935416
],
[
106.556582195013,
-6.68497003983464
],
[
106.541310000657,
-6.71486999865072
],
[
106.542630000375,
-6.74058999942815
],
[
106.550740756582,
-6.7473471734325
],
[
106.533284161136,
-6.75148465469226
],
[
106.524773753407,
-6.76232523192311
],
[
106.498398062322,
-6.75218427058684
],
[
106.46682763259,
-6.75104031405846
],
[
106.459021692598,
-6.73381922767441
],
[
106.481760000125,
-6.72494999944212
],
[
106.504030000085,
-6.70412999979885
],
[
106.51431934866,
-6.65951255475977
],
[
106.522270001261,
-6.66321000044036
]
]
]
]
},
"geometry_name": "the_geom",
"properties": {
"fid": 37287,
"desa": "MALASARI",
"provinsi": "JAWA BARAT",
"kabkot": "BOGOR",
"kecamatan": "NANGGUNG",
"post_code": null,
"city_code": "",
"ph_code": "",
"locker_cod": "",
"area_code": "",
"id": 37287,
"cluster_area_code": "",
"service_ty": null
}
}
],
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:EPSG::4326"
}
}
}

7
src/dummy_data/route.json

@ -1,7 +0,0 @@
{
"routes": [
{
"geometry": "hldhx@lnau`BCG_EaC??cFjAwDjF??uBlKMd@}@z@??aC^yk@z_@se@b[wFdE??wFfE}NfIoGxB_I\\gG}@eHoCyTmPqGaBaHOoD\\??yVrGotA|N??o[N_STiwAtEmHGeHcAkiA}^aMyBiHOkFNoI`CcVvM??gG^gF_@iJwC??eCcA]OoL}DwFyCaCgCcCwDcGwHsSoX??wI_EkUFmq@hBiOqBgTwS??iYse@gYq\\cp@ce@{vA}s@csJqaE}{@iRaqE{lBeRoIwd@_T{]_Ngn@{PmhEwaA{SeF_u@kQuyAw]wQeEgtAsZ}LiCarAkVwI}D??_}RcjEinPspDwSqCgs@sPua@_OkXaMeT_Nwk@ob@gV}TiYs[uTwXoNmT{Uyb@wNg]{Nqa@oDgNeJu_@_G}YsFw]kDuZyDmm@i_@uyIJe~@jCg|@nGiv@zUi_BfNqaAvIow@dEed@dCcf@r@qz@Egs@{Acu@mCum@yIey@gGig@cK_m@aSku@qRil@we@{mAeTej@}Tkz@cLgr@aHko@qOmcEaJw~C{w@kai@qBchBq@kmBS{kDnBscBnFu_Dbc@_~QHeU`IuyDrC_}@bByp@fCyoA?qMbD}{AIkeAgBk_A_A{UsDke@gFej@qH{o@qGgb@qH{`@mMgm@uQus@kL{_@yOmd@ymBgwE}x@ouBwtA__DuhEgaKuWct@gp@cnBii@mlBa_@}|Asj@qrCg^eaC}L{dAaJ_aAiOyjByH{nAuYu`GsAwXyn@ywMyOyqD{_@cfIcDe}@y@aeBJmwA`CkiAbFkhBlTgdDdPyiB`W}xDnSa}DbJyhCrXitAhT}x@bE}Z_@qW_Kwv@qKaaAiBgXvIm}A~JovAxCqW~WanB`XewBbK{_A`K}fBvAmi@xBycBeCauBoF}}@qJioAww@gjHaPopA_NurAyJku@uGmi@cDs[eRaiBkQstAsQkcByNmaCsK_uBcJgbEw@gkB_@ypEqDoqSm@eZcDwjBoGw`BoMegBaU_`Ce_@_uBqb@ytBwkFqiT_fAqfEwe@mfCka@_eC_UmlB}MmaBeWkkDeHwqAoX}~DcBsZmLcxBqOwqE_DkyAuJmrJ\\o~CfIewG|YibQxBssB?es@qGciA}RorAoVajA_nAodD{[y`AgPqp@mKwr@ms@umEaW{dAmb@umAw|@ojBwzDaaJsmBwbEgdCsrFqhAihDquAi`Fux@}_Dui@_eB_u@guCuyAuiHukA_lKszAu|OmaA{wKm}@clHs_A_rEahCssKo\\sgBsSglAqk@yvDcS_wAyTwpBmPc|BwZknFoFscB_GsaDiZmyMyLgtHgQonHqT{hKaPg}Dqq@m~Hym@c`EuiBudIabB{hF{pWifx@snAw`GkFyVqf@y~BkoAi}Lel@wtc@}`@oaXi_C}pZsi@eqGsSuqJ|Lqeb@e]kgPcaAu}SkDwzGhn@gjYh\\qlNZovJieBqja@ed@siO{[ol\\kCmjMe\\isHorCmec@uLebB}EqiBaCg}@m@qwHrT_vFps@kkI`uAszIrpHuzYxx@e{Crw@kpDhN{wBtQarDy@knFgP_yCu\\wyCwyA{kHo~@omEoYmoDaEcPiuAosDagD}rO{{AsyEihCayFilLaiUqm@_bAumFo}DgqA_uByi@swC~AkzDlhA}xEvcBa}Cxk@ql@`rAo|@~bBq{@``Bye@djDww@z_C_cAtn@ye@nfC_eC|gGahH~s@w}@``Fi~FpnAooC|u@wlEaEedRlYkrPvKerBfYs}Arg@m}AtrCkzElw@gjBbh@woBhR{gCwGkgCc[wtCuOapAcFoh@uBy[yBgr@c@iq@o@wvEv@sp@`FajBfCaq@fIipAdy@ewJlUc`ExGuaBdEmbBpBssArAuqBBg}@s@g{AkB{bBif@_bYmC}r@kDgm@sPq_BuJ_s@{X_{AsK_d@eM{d@wVgx@oWcu@??aDmOkNia@wFoSmDyMyCkPiBePwAob@XcQ|@oNdCoSfFwXhEmOnLi\\lbAulB`X_d@|k@au@bc@oc@bqC}{BhwDgcD`l@ed@??bL{G|a@eTje@oS~]cLr~Bgh@|b@}Jv}EieAlv@sPluD{z@nzA_]`|KchCtd@sPvb@wSb{@ko@f`RooQ~e[upZbuIolI|gFafFzu@iq@nMmJ|OeJn^{Qjh@yQhc@uJ~j@iGdd@kAp~BkBxO{@|QsAfYgEtYiGd]}Jpd@wRhVoNzNeK`j@ce@vgK}cJnSoSzQkVvUm^rSgc@`Uql@xIq\\vIgg@~kDyq[nIir@jNoq@xNwc@fYik@tk@su@neB}uBhqEesFjoGeyHtCoD|D}Ed|@ctAbIuOzqB_}D~NgY`\\um@v[gm@v{Cw`G`w@o{AdjAwzBh{C}`Gpp@ypAxn@}mAfz@{bBbNia@??jIab@`CuOlC}YnAcV`@_^m@aeB}@yk@YuTuBg^uCkZiGk\\yGeY}Lu_@oOsZiTe[uWi[sl@mo@soAauAsrBgzBqgAglAyd@ig@asAcyAklA}qAwHkGi{@s~@goAmsAyDeEirB_{B}IsJuEeFymAssAkdAmhAyTcVkFeEoKiH}l@kp@wg@sj@ku@ey@uh@kj@}EsFmG}Jk^_r@_f@m~@ym@yjA??a@cFd@kBrCgDbAUnAcBhAyAdk@et@??kF}D??OL"
}
]
}

257
src/dummy_data/route2.json

@ -1,257 +0,0 @@
{
"geocoded_waypoints": [
{
"geocoder_status": "OK",
"place_id": "ChIJT2zELKHxaS4RR5fpIKhtekA",
"types": [
"street_address"
]
},
{
"geocoder_status": "OK",
"place_id": "ChIJdbdzpG7xaS4RUCaaEC6NIOo",
"types": [
"street_address"
]
}
],
"routes": [
{
"bounds": {
"northeast": {
"lat": -6.245234399999999,
"lng": 106.8006477
},
"southwest": {
"lat": -6.2623544,
"lng": 106.7885345
}
},
"copyrights": "Map data ©2021",
"legs": [
{
"distance": {
"text": "3.0 km",
"value": 2992
},
"duration": {
"text": "9 mins",
"value": 552
},
"end_address": "Jl. Melawai 5 No.172, RT.3/RW.1, Melawai, Kec. Kby. Baru, Kota Jakarta Selatan, Daerah Khusus Ibukota Jakarta 12160, Indonesia",
"end_location": {
"lat": -6.245234399999999,
"lng": 106.8006477
},
"start_address": "Jl. Bri Radio Dalam No.34/4, RT.2/RW.15, Gandaria Utara, Kec. Kby. Baru, Kota Jakarta Selatan, Daerah Khusus Ibukota Jakarta 12140, Indonesia",
"start_location": {
"lat": -6.2623544,
"lng": 106.7885345
},
"steps": [
{
"distance": {
"text": "1.5 km",
"value": 1495
},
"duration": {
"text": "4 mins",
"value": 221
},
"end_location": {
"lat": -6.2493628,
"lng": 106.7918222
},
"html_instructions": "Head <b>north</b> on <b>Jl. Radio Dalam Raya</b> toward <b>Jl. Dwijaya Raya</b><div style=\"font-size:0.9em\">Pass by Alfamart Radio Dalam 4 (on the right)</div>",
"polyline": {
"points": "tbfe@icxjSOEs@M}@K}C]m@KUKg@G[EKAQCaAO_@GGAoB[SEaCa@e@Ga@GuB]yA[{Ba@iAYkA[a@KqAi@w@WaA[KCgAYQCMAw@I}AKUCeAOQCoAUMCoAQyAQc@EcBKe@C}@IC?g@E_AG"
},
"start_location": {
"lat": -6.2623544,
"lng": 106.7885345
},
"travel_mode": "DRIVING"
},
{
"distance": {
"text": "0.5 km",
"value": 532
},
"duration": {
"text": "2 mins",
"value": 99
},
"end_location": {
"lat": -6.2491213,
"lng": 106.7959681
},
"html_instructions": "Turn <b>right</b> onto <b>Jl. Kramat Pela</b>",
"maneuver": "turn-right",
"polyline": {
"points": "nqce@{wxjSMA\\sBJm@JOBQFa@h@cC@EN_@Le@Hc@?QBQBIDQ@Q@O?UASCSAMCGEGU]QSWWQUq@q@MGQEGAKA"
},
"start_location": {
"lat": -6.2493628,
"lng": 106.7918222
},
"travel_mode": "DRIVING"
},
{
"distance": {
"text": "25 m",
"value": 25
},
"duration": {
"text": "1 min",
"value": 4
},
"end_location": {
"lat": -6.249124,
"lng": 106.7961904
},
"html_instructions": "Turn <b>right</b> toward <b>Jl. Barito II</b>",
"maneuver": "turn-right",
"polyline": {
"points": "~oce@yqyjSAK@_@"
},
"start_location": {
"lat": -6.2491213,
"lng": 106.7959681
},
"travel_mode": "DRIVING"
},
{
"distance": {
"text": "0.2 km",
"value": 154
},
"duration": {
"text": "1 min",
"value": 36
},
"end_location": {
"lat": -6.249612600000001,
"lng": 106.7974484
},
"html_instructions": "Turn <b>right</b> onto <b>Jl. Barito II</b>",
"maneuver": "turn-right",
"polyline": {
"points": "~oce@esyjS`@_@P[JSJ]DM@KH}@Bu@"
},
"start_location": {
"lat": -6.249124,
"lng": 106.7961904
},
"travel_mode": "DRIVING"
},
{
"distance": {
"text": "0.4 km",
"value": 414
},
"duration": {
"text": "1 min",
"value": 77
},
"end_location": {
"lat": -6.2459198,
"lng": 106.7979545
},
"html_instructions": "Turn <b>left</b> onto <b>Jl. Panglima Polim</b> (signs for <b>Senayan</b>/<wbr/><b>Semanggi</b>)<div style=\"font-size:0.9em\">Pass by ATM Bank UOB (on the left)</div>",
"maneuver": "turn-left",
"polyline": {
"points": "`sce@a{yjSmBMgDUyBQGAyDW[CgAIk@E"
},
"start_location": {
"lat": -6.249612600000001,
"lng": 106.7974484
},
"travel_mode": "DRIVING"
},
{
"distance": {
"text": "0.2 km",
"value": 220
},
"duration": {
"text": "1 min",
"value": 48
},
"end_location": {
"lat": -6.245905899999999,
"lng": 106.7999397
},
"html_instructions": "Turn <b>right</b> onto <b>Jl. Melawai Raya</b><div style=\"font-size:0.9em\">Pass by MM Juice Melawai (on the right)</div>",
"maneuver": "turn-right",
"polyline": {
"points": "~{be@e~yjS?SAq@?S?A?]Cg@AKD_F"
},
"start_location": {
"lat": -6.2459198,
"lng": 106.7979545
},
"travel_mode": "DRIVING"
},
{
"distance": {
"text": "74 m",
"value": 74
},
"duration": {
"text": "1 min",
"value": 33
},
"end_location": {
"lat": -6.2452361,
"lng": 106.7999455
},
"html_instructions": "Turn <b>left</b> after HAZEL Brew Coffee (on the right)",
"maneuver": "turn-left",
"polyline": {
"points": "|{be@sjzjSO?C?_@?qAA"
},
"start_location": {
"lat": -6.245905899999999,
"lng": 106.7999397
},
"travel_mode": "DRIVING"
},
{
"distance": {
"text": "78 m",
"value": 78
},
"duration": {
"text": "1 min",
"value": 34
},
"end_location": {
"lat": -6.245234399999999,
"lng": 106.8006477
},
"html_instructions": "Turn <b>right</b> onto <b>Jl. Melawai 9</b><div style=\"font-size:0.9em\">Destination will be on the left</div>",
"maneuver": "turn-right",
"polyline": {
"points": "vwbe@ujzjSAkC"
},
"start_location": {
"lat": -6.2452361,
"lng": 106.7999455
},
"travel_mode": "DRIVING"
}
],
"traffic_speed_entry": [],
"via_waypoint": []
}
],
"overview_polyline": {
"points": "tbfe@icxjScAS{Ei@m@KUKcAM_C]mGeAgAOoEy@eE{@mBg@iCaAmA_@yA]eAKsBOwAS}AYiDc@kF_@yBOh@aDJOBQFa@h@cCPe@ViABc@H[Ba@Ai@Ea@IOg@q@i@m@q@q@MGYGKAAK@_@`@_@\\o@Pk@JiABu@mBMaHg@eHg@k@E?SAeAEsAD_FO?c@?qAAAkC"
},
"summary": "Jl. Radio Dalam Raya",
"warnings": [],
"waypoint_order": []
}
],
"status": "OK"
}

259
src/dummy_data/route3.geojson

@ -1,259 +0,0 @@
{
"type": "FeatureCollection",
"features": [
{
"id": "sales.1",
"geometry_name": "the_geom",
"type": "Feature",
"properties": {
"id": "sales.1",
"name": "Sales 1"
},
"geometry": {
"type": "LineString",
"coordinates": [
[
106.78853,
-6.26235
],
[
106.78863,
-6.26201
],
[
106.78884,
-6.26091
],
[
106.7889,
-6.26068
],
[
106.78896,
-6.26057
],
[
106.78903,
-6.26023
],
[
106.78918,
-6.25959
],
[
106.78953,
-6.25824
],
[
106.78961,
-6.25788
],
[
106.7899,
-6.25684
],
[
106.7902,
-6.25585
],
[
106.7904,
-6.2553
],
[
106.79073,
-6.25461
],
[
106.79089,
-6.25422
],
[
106.79104,
-6.25377
],
[
106.7911,
-6.25342
],
[
106.79118,
-6.25284
],
[
106.79128,
-6.2524
],
[
106.79141,
-6.25193
],
[
106.79159,
-6.25108
],
[
106.79175,
-6.2499
],
[
106.79183,
-6.24929
],
[
106.79264,
-6.2495
],
[
106.79272,
-6.24956
],
[
106.79281,
-6.24958
],
[
106.79298,
-6.24962
],
[
106.79364,
-6.24983
],
[
106.79383,
-6.24992
],
[
106.7942,
-6.25004
],
[
106.79438,
-6.25006
],
[
106.79452,
-6.25011
],
[
106.79469,
-6.25013
],
[
106.7949,
-6.25012
],
[
106.79507,
-6.25009
],
[
106.79515,
-6.25004
],
[
106.7954,
-6.24984
],
[
106.79563,
-6.24963
],
[
106.79588,
-6.24938
],
[
106.79592,
-6.24931
],
[
106.79596,
-6.24918
],
[
106.79597,
-6.24912
],
[
106.79603,
-6.24911
],
[
106.79619,
-6.24912
],
[
106.79635,
-6.24929
],
[
106.79659,
-6.24944
],
[
106.79681,
-6.24953
],
[
106.79718,
-6.24959
],
[
106.79745,
-6.24961
],
[
106.79752,
-6.24906
],
[
106.79772,
-6.24761
],
[
106.79792,
-6.24614
],
[
106.79795,
-6.24592
],
[
106.79805,
-6.24592
],
[
106.7984,
-6.24591
],
[
106.79882,
-6.24588
],
[
106.79994,
-6.24591
],
[
106.79994,
-6.24583
],
[
106.79994,
-6.24565
],
[
106.79995,
-6.24524
],
[
106.80065,
-6.24523
]
]
}
}
]
}

85
src/dummy_data/sales.geojson

@ -1,85 +0,0 @@
{
"type": "FeatureCollection",
"features": [
{
"id": "sales.1",
"geometry_name": "the_geom",
"type": "Feature",
"properties": {
"id": "sales.1",
"name": "Sales 1"
},
"geometry": {
"type": "Point",
"coordinates": [
106.79569244384766,
-6.2395378839383016
]
}
},
{
"id": "sales.2",
"geometry_name": "the_geom",
"type": "Feature",
"properties": {
"id": "sales.2",
"name": "Sales 2"
},
"geometry": {
"type": "Point",
"coordinates": [
106.78788185119627,
-6.2620624718682665
]
}
},
{
"id": "sales.3",
"geometry_name": "the_geom",
"type": "Feature",
"properties": {
"id": "sales.3",
"name": "Sales 3"
},
"geometry": {
"type": "Point",
"coordinates": [
106.81011199951172,
-6.249349850172153
]
}
},
{
"id": "sales.4",
"geometry_name": "the_geom",
"type": "Feature",
"properties": {
"id": "sales.4",
"name": "Sales 4"
},
"geometry": {
"type": "Point",
"coordinates": [
106.81543350219727,
-6.215817763782759
]
}
},
{
"id": "sales.5",
"geometry_name": "the_geom",
"type": "Feature",
"properties": {
"id": "sales.5",
"name": "Sales 5"
},
"geometry": {
"type": "Point",
"coordinates": [
106.80745124816895,
-6.2746041510497355
]
}
}
]
}

12
src/views/Dashboard/DashboardBOD.js

@ -151,7 +151,7 @@ const DashboardBOD = (props) => {
}
const getProjectPerBudgetHealth = async () => {
const URL = `${BASE_OSPRO}/api/dashboard/get-total-project-per-budget-health`
const URL = `${BASE_OSPRO}/api/dashboard/get-total-project-per-budget-health/${moment().format('YYYY')}/${company_id}/${all_project}/${hierarchy}`
const result = await axios.get(URL, HEADER).then(res => res).catch(err => err.response)
const content = "Get Project by Budget Health.";
@ -174,7 +174,7 @@ const DashboardBOD = (props) => {
}
const getProjectBudgetHealthPerDivision = async () => {
const URL = `${BASE_OSPRO}/api/dashboard/get-total-project-budget-health-per-division`
const URL = `${BASE_OSPRO}/api/dashboard/get-total-project-budget-health-per-division/${moment().format('YYYY')}/${company_id}/${all_project}/${hierarchy}`
const result = await axios.get(URL, HEADER).then(res => res).catch(err => err.response)
const content = "Get Project by Schedule Health per Division.";
@ -198,7 +198,7 @@ const DashboardBOD = (props) => {
}
const getProjectScheduleHealthPerDivision = async () => {
const URL = `${BASE_OSPRO}/api/dashboard/get-total-project-schedule-health-per-division`
const URL = `${BASE_OSPRO}/api/dashboard/get-total-project-schedule-health-per-division/${moment().format('YYYY')}/${company_id}/${all_project}/${hierarchy}`
const result = await axios.get(URL, HEADER).then(res => res).catch(err => err.response)
const content = "Get Project by Schedule Health.";
@ -246,7 +246,7 @@ const DashboardBOD = (props) => {
}
const getTotalProjectPerDivision = async () => {
const URL = `${BASE_OSPRO}/api/dashboard/get-total-project-per-division`
const URL = `${BASE_OSPRO}/api/dashboard/get-total-project-per-division/${moment().format('YYYY')}/${company_id}/${all_project}/${hierarchy}`
const result = await axios.get(URL, HEADER).then(res => res).catch(err => err.response)
const content = "Get Project by Division.";
@ -271,7 +271,7 @@ const DashboardBOD = (props) => {
}
const getTotalProjectValuePerDivision = async () => {
const URL = `${BASE_OSPRO}/api/dashboard/get-total-project-value-per-division/${moment().format('YYYY')}`
const URL = `${BASE_OSPRO}/api/dashboard/get-total-project-value-per-division/${moment().format('YYYY')}/${company_id}/${all_project}/${hierarchy}`
const result = await axios.get(URL, HEADER).then(res => res).catch(err => err.response)
const content = "Get Project Value by Division";
@ -300,7 +300,7 @@ const DashboardBOD = (props) => {
return;
}
setOpenDetailedView(true);
const URL = `${BASE_OSPRO}/api/dashboard/get-detail-expenditure`
const URL = `${BASE_OSPRO}/api/dashboard/get-detail-expenditure/${moment().format('YYYY')}/${company_id}/${all_project}/${hierarchy}`
const result = await axios.get(URL, HEADER).then(res => res).catch(err => err.response)
const content = "Get Detail Expenditure";

1698
src/views/Dashboard/DashboardProject.js.save

File diff suppressed because it is too large Load Diff

1698
src/views/Dashboard/DashboardProject.js.save.1

File diff suppressed because it is too large Load Diff

37
src/views/DashboardProject/chatDashboard.js

@ -1,37 +0,0 @@
import React from 'react';
const ChatDashboard = (props) => {
const { dataParams } = props;
const renderComment = (items) => {
return items.map((item, idx) => {
return (
<div className="chat-content" key={idx}>
<div className='chat-body'>
<div className='chat-header'>
{item.comment_by}
</div>
<div className='chat-body-content'>
{item.comment}
</div>
<div className='chat-footer'>
{item.comment_created}
</div>
</div>
</div>
)
})
}
return (
<div style={{ margin: '0 5px' }} className="box-header-dashboard-project">
<div style={{ display: 'flex', justifyContent: 'center' }}>
<div style={{ marginBottom: '5px', fontSize: '0.8rem', fontWeight: '500' }}>COMMUNICATION</div>
</div>
<div className='chat'>
{renderComment(dataParams)}
</div>
</div>
);
}
export default ChatDashboard;

34
src/views/DashboardProject/ganttDashboard.js

@ -1,34 +0,0 @@
import React, { useEffect, useMemo, useState } from 'react';
import Timeline from 'react-calendar-timeline'
// make sure you include the timeline stylesheet or the timeline will not be styled
import 'react-calendar-timeline/lib/Timeline.css'
import { useParams } from 'react-router-dom';
// import moment from 'moment';
// import { USER_VERSION_GANTT_SEARCH, BASE_SIMPRO_LUMEN } from '../../../const/ApiConst';
// import axios from "../../../const/interceptorApi"
const token = localStorage.getItem("token")
const Gantt = (props) => {
const { ID } = useParams();
const { GANTTID } = useParams();
const url = `https://konstruksi-gantt.ospro.id/view-mode/index.html?base_url=${BASE_OSPRO}/api&gantt_id=${GANTT_ID}&proyek_id=${PROJECT_ID}&token=${token}&ro=1`
const RenderGantt = () => (
<iframe
id="frame-gantt"
src={url}
style={{
width: '100%',
height: '50vh',
}}
scrolling="no"
frameBorder="0"
></iframe>
)
return (
<div>
<RenderGantt />
</div>
);
}
export default Gantt;

275
src/views/DashboardProject/index.js

@ -1,275 +0,0 @@
import React, { useEffect, useState } from 'react';
import { Row, Col, Select, Divider } from 'antd';
import moment from 'moment'
import Gantt from './ganttDashboard';
import ChatDashboard from './chatDashboard';
import axios from 'axios'
import { NotificationContainer, NotificationManager } from 'react-notifications';
import { useParams } from 'react-router-dom';
import { Badge } from 'reactstrap';
import { BASE_OSPRO, BASE_INTEGRATION_V1, TOKEN_ADW } from '../../const/ApiConst';
import {formatRibuanDecimal} from "../../const/CustomFunc";
import ProgressBar from "./progressBar";
import numeral from 'numeral';
function BoxDashboard({ value, title, secondaryTitle, icon, bgColor }) {
return (
<div style={{ backgroundColor: bgColor }} className='box-header-dashboard-project'>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<div style={{ fontSize: '0.8rem', fontWeight: 500, color: '#fff', textTransform: 'uppercase' }}>{title}</div>
<div>{icon}</div>
</div>
<div style={{ fontSize: '1rem', fontWeight: 500, color: '#fff' }}>{value}</div>
</div>
)
}
function RenderHealthProject({params}){
if (params == "on-budget") {
return (<Badge style = {{fontSize:"18px"}} color="success">On Budget</Badge>)
} else if (params == "warning") {
return (<Badge style = {{fontSize:"18px"}} color="warning">Warning</Badge>)
} else {
return (<Badge style = {{fontSize:"18px"}} color="danger">Danger</Badge>)
}
}
const DashboardProject = () => {
const { ID } = useParams();
const [STATUSPROJECT, SET_STATUSPROJECT] = useState([])
const [PROJECTMGR, SET_PROJECTMGR] = useState([])
const [RO, SET_RO] = useState([])
// Schedule
const [STARTDATE, SET_STARTDATE] = useState([])
const [BASELINEFINISHDATE, SET_BASELINEFINISHDATE] = useState([])
const [ESTFINISHDATE, SET_ESTFINISHDATE] = useState([])
// Financials
const [BCWP, SET_BCWP] = useState([])
const [ACWP, SET_ACWP] = useState([])
const [VARIANCE, SET_VARIANCE] = useState([])
const [PROGRESS, SET_PROGRESS] = useState([])
const [BUDGET, SET_BUDGET] = useState([])
const [PROJECTNAME, SET_PROJECTNAME] = useState([])
const [CURRENCYSYMBOL, SET_CURRENCYSYMBOL] = useState([])
const [BUDGETHEALTH, SET_BUDGETHEALTH] = useState([])
const [COMMENT, SET_COMMENT] = useState([])
const [MANPOWER, SET_MANPOWER] = useState([0])
const token = localStorage.getItem("token")
const HEADER = {
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`
}
}
const HEADER_INTEGRASI = {
headers: {
"Content-Type": "application/json",
"Authorization": `${TOKEN_ADW}`
}
}
const getProjectDetail = async () => {
const URL = `${BASE_OSPRO}/api/project/dashboard/${ID}`
const result = await axios.get(URL, HEADER).then(res => res).catch(err => err.response)
if (result.data.code !== 200) {
NotificationManager.error(result.data.message, 'Failed');
}
if(result.data.code == 200) {
let resData = result.data.data;
SET_BUDGET(resData.rencana_biaya)
SET_PROJECTMGR(resData.pm)
SET_RO(resData.company)
SET_PROJECTNAME(resData.name_project)
SET_STARTDATE(resData.start)
SET_BASELINEFINISHDATE(resData.finish)
SET_CURRENCYSYMBOL(resData.currency_symbol)
SET_BUDGETHEALTH(resData.budget_health)
SET_ACWP(resData.actual_cost)
SET_PROGRESS(resData.progress)
SET_COMMENT(resData.comment)
SET_MANPOWER(resData.man_power)
getDataCostActual(resData.kode_sortname);
}
}
const getDataCostActual = async (kode_project) => {
const URL = `${BASE_INTEGRATION_V1}/api/project_cost?project_no=${kode_project}`
const result = await axios.get(URL, HEADER_INTEGRASI).then(res => res).catch(err => err.response)
if (!result.data.data) {
NotificationManager.error('Integrasi Cost Actual Failed', 'Failed');
}else {
SET_ACWP(result.data.data.total_cost)
}
}
useEffect(() => {
getProjectDetail();
}, [])
return (
<div style={{ margin: "10px" }}>
<Row>
<Col span={9}>
<div style={{ display: 'flex', justifyContent: 'space-between', margin: '0 5px' }} className="box-header-dashboard-project">
<div><i style={{ color: 'teal' }} class="zmdi zmdi-assignment zmdi-hc-lg"></i></div>
<div style={{ textTransform: 'uppercase' }}>Project </div>
<div style={{ fontWeight: 500, color: '#404040', textTransform: 'uppercase' }}> {PROJECTNAME}</div>
</div>
</Col>
<Col span={4}>
<div style={{ display: 'flex', justifyContent: 'space-between', margin: '0 5px' }} className="box-header-dashboard-project">
<div><i style={{ color: '#0284c7' }} class="zmdi zmdi-account zmdi-hc-lg"></i></div>
<div style={{ textTransform: 'uppercase' }}>PM</div>
<div style={{ fontWeight: 500, color: '#404040', textTransform: 'uppercase' }}>{PROJECTMGR}</div>
</div>
</Col>
<Col span={7}>
<div style={{ display: 'flex', justifyContent: 'space-between', margin: '0 5px' }} className="box-header-dashboard-project">
<div><i style={{ color: '#b91c1c' }} class="zmdi zmdi-home zmdi-hc-lg"></i></div>
<div style={{ textTransform: 'uppercase' }}>Customer</div>
<div style={{ fontWeight: 500, color: '#404040', textTransform: 'uppercase' }}>{RO}</div>
</div>
</Col>
<Col span={4}>
<div style={{ display: 'flex', justifyContent: 'space-between', margin: '0 5px' }} className="box-header-dashboard-project">
<div><i style={{ color: '#e68a00' }} class="zmdi zmdi-calendar-alt zmdi-hc-lg"></i></div>
<div style={{ textTransform: 'uppercase' }}>Date</div>
<div style={{ fontWeight: 500, color: '#404040' }}>{moment().format("DD-MM-YYYY")}</div>
</div>
</Col>
</Row>
<div style={{ paddingTop: 20 }}>
<Row>
<Col span={9}>
<div style={{ margin: '0 5px' }} className="box-header-dashboard-project">
<div style={{ margin: '5px 0' }}><h6>SCHEDULE</h6></div>
<div style={{ padding: '5px 0' }}>
<Row>
<Col span={2}><i style={{ color: 'teal' }} class="zmdi zmdi-calendar-alt zmdi-hc-lg"></i></Col>
<Col span={22}>
<div style={{ textTransform: 'uppercase', display: 'flex', justifyContent: 'space-between' }}>
<div>Start Date</div>
<div style={{ fontWeight: 500, color: '#8c8c8c' }}>{moment(STARTDATE).format("LL")}</div>
</div>
</Col>
</Row>
</div>
<div style={{ padding: '5px 0' }}>
<Row>
<Col span={2}><i style={{ color: 'teal' }} class="zmdi zmdi-calendar-alt zmdi-hc-lg"></i></Col>
<Col span={22}>
<div style={{ textTransform: 'uppercase', display: 'flex', justifyContent: 'space-between' }}>
<div>Baseline Finish Date</div>
<div style={{ fontWeight: 500, color: '#8c8c8c' }}>{moment(BASELINEFINISHDATE).format("LL")}</div>
</div>
</Col>
</Row>
</div>
<div style={{ padding: '5px 0' }}>
<Row>
<Col span={2}><i style={{ color: 'teal' }} class="zmdi zmdi-calendar-alt zmdi-hc-lg"></i></Col>
<Col span={22}>
<div style={{ textTransform: 'uppercase', display: 'flex', justifyContent: 'space-between' }}>
<div>Estimated Finish Date</div>
<div style={{ fontWeight: 500, color: '#8c8c8c' }}>{moment(ESTFINISHDATE).format("LL")}</div>
</div>
</Col>
</Row>
</div>
</div>
</Col>
<Col span={10}>
<div style={{ margin: '0 5px' }} className="box-header-dashboard-project">
<div style={{ margin: '5px 0' }}><h6>FINANCIALS</h6></div>
<div style={{ padding: '5px 0' }}>
<Row>
<Col span={2}><i style={{ color: '#059669' }} class="zmdi zmdi-money zmdi-hc-lg"></i></Col>
<Col span={22}>
<div style={{ textTransform: 'uppercase', display: 'flex', justifyContent: 'space-between' }}>
<div>Budget Proyek</div>
<div style={{ fontWeight: 500, color: '#8c8c8c' }}>{`${formatRibuanDecimal(BUDGET)}`}</div>
</div>
</Col>
</Row>
</div>
<div style={{ padding: '5px 0' }}>
<Row>
<Col span={2}><i style={{ color: '#059669' }} class="zmdi zmdi-money zmdi-hc-lg"></i></Col>
<Col span={22}>
<div style={{ textTransform: 'uppercase', display: 'flex', justifyContent: 'space-between' }}>
<div>Actual Cost</div>
<div style={{ fontWeight: 500, color: '#8c8c8c' }}>{`${formatRibuanDecimal(ACWP)}`}</div>
</div>
</Col>
</Row>
</div>
<div style={{ padding: '5px 0' }}>
<Row>
<Col span={2}><i style={{ color: '#059669' }} class="zmdi zmdi-money zmdi-hc-lg"></i></Col>
<Col span={22}>
<div style={{ textTransform: 'uppercase', display: 'flex', justifyContent: 'space-between' }}>
<div>Variance</div>
<div style={{ fontWeight: 500, color: '#8c8c8c' }}>{`${formatRibuanDecimal(BUDGET - ACWP)}`}</div>
</div>
</Col>
</Row>
</div>
</div>
</Col>
<Col span={5}>
<div style={{ backgroundColor: "#059669" }} className='box-header-dashboard-project'>
<div style={{ display: 'flex', justifyContent: 'center' }}>
<div style={{ fontSize: '0.8rem', fontWeight: 500, color: '#fff', textTransform: 'uppercase' }}>Progress</div>
</div>
<ProgressBar bgcolor="#ffc355" completed={PROGRESS} />
</div>
<Row>
<Col span={12}>
<div style={{ margin: '5px 0' }} className="box-header-dashboard-project">
<div style={{ display: 'flex', justifyContent: 'center' }}>
<div style={{ marginBottom: '5px', fontSize: '0.7rem', fontWeight: '500' }}>HEALTH PROJECT</div>
</div>
<div style={{ display: 'flex', justifyContent: 'space-evenly', }}>
<RenderHealthProject params = {`${BUDGETHEALTH}`}/>
</div>
</div>
</Col>
<Col span={12}>
<div style={{ margin: '5px 0' }} className="box-header-dashboard-project">
<div style={{ display: 'flex', justifyContent: 'center' }}>
<div style={{ marginBottom: '5px', fontSize: '0.7rem', fontWeight: '500' }}>MANPOWER</div>
</div>
<div style={{ display: 'flex', justifyContent: 'space-evenly', }}>
<div style={{ fontWeight: 500, color: '#404040', fontSize: '18px', textTransform: 'uppercase' }}>{MANPOWER}</div>
</div>
</div>
</Col>
</Row>
{/* </div> */}
</Col>
</Row>
</div>
<div style={{ paddingTop: 20 }}>
<Row>
<Col span={19}>
</Col>
<Col span={5}>
<ChatDashboard
dataParams = {COMMENT}/>
</Col>
</Row>
</div>
</div>
);
}
export default DashboardProject;

37
src/views/DashboardProject/progressBar.js

@ -1,37 +0,0 @@
import React from "react";
const ProgressBar = (props) => {
const { bgcolor, completed } = props;
const containerStyles = {
height: 25,
width: '100%',
backgroundColor: "#e0e0de",
borderRadius: 50,
margin: 0
}
const fillerStyles = {
height: '100%',
width: `${completed}%`,
backgroundColor: bgcolor,
borderRadius: 'inherit',
textAlign: 'right'
}
const labelStyles = {
padding: 5,
color: 'white',
fontWeight: 'bold'
}
return (
<div style={containerStyles}>
<div style={fillerStyles}>
<span style={labelStyles}>{`${completed}%`}</span>
</div>
</div>
);
};
export default ProgressBar;

72
src/views/DashboardProject/tableDashboard.js

@ -1,72 +0,0 @@
import React from 'react';
import { Table, Tag, Space } from 'antd';
const columns = [
{
title: 'No',
dataIndex: 'carNo',
key: 'carNo',
fixed: 'left',
},
{
title: 'Description',
dataIndex: 'description',
key: 'description',
width: 350
},
{
title: 'Severity',
dataIndex: 'severity',
key: 'severity',
render: text => {
return text == 'low' ? <div className="badge" style={{ backgroundColor: '#e6e600' }}>LOW</div> :
text == 'medium' ? <div className="badge badge-orange" style={{ backgroundColor: 'orange' }}>MEDIUM</div> :
<div className="badge badge-danger">HIGH</div>
},
},
{
title: 'Status',
dataIndex: 'status',
key: 'status',
render: text => {
return text == 'open' ? <div className="badge badge-primary">OPEN</div> :
text == 'on-progress' ? <div className="badge badge-warning">ON PROGRESS</div> :
<div className="badge badge-success">DONE</div>
},
},
{
title: 'Assigned',
dataIndex: 'assigned',
key: 'assigned',
},
{
title: 'Due',
dataIndex: 'due',
key: 'due',
}
];
const data = [
{
key: '1',
carNo: 'RIS001',
description: 'Test Analyst on unplanned leave, risk to project if leave extends pas 5/20',
severity: 'medium',
status: 'on-progress',
due: '05/04/2022',
assigned: 'John Lennon'
},
{
key: '2',
carNo: 'RIS002',
description: 'Coffee machine broken, result in extra long breaks to find coffee',
severity: 'low',
status: 'open',
due: '14/011/2022',
assigned: 'Robert William'
},
];
const TableDashboard = () => {
return (
<Table size="small" columns={columns} dataSource={data} scroll={{ y: 300 }} />
);
}
export default TableDashboard;

719
src/views/Map/Map.js

File diff suppressed because it is too large Load Diff

0
src/views/Master/MasterCountry/MasterCountry.css

51
src/views/Master/MasterCountry/MasterCountry.js

@ -1,51 +0,0 @@
import React, { Component } from 'react'
import DataTable from '../../../components/DataTable'
import {API_LIST_DATA_COUNTRY, API_INSERT_DATA_COUNTRY, API_UPDATE_DATA_COUNTRY, API_DELETE_DATA_COUNTRY } from '../../../const/ApiConst.js'
const columns = [{
dataField: 'id',
alias: "Id",
showInput: false,
type: "number",
state: 0
}, {
dataField: 'country_name',
alias: "Country Name",
showInput: true,
type: "text",
state: ""
}, {
dataField: 'last_updated',
alias: "Last Updated",
showInput: false,
type: "text",
state: ""
}];
class MasterCountry extends Component {
constructor(props) {
super(props)
this.state = {}
}
componentDidMount() {}
render() {
return (
<div>
<DataTable
title="Country"
columns={columns}
urlParamGet={API_LIST_DATA_COUNTRY}
urlParamInsert={API_INSERT_DATA_COUNTRY}
urlParamUpdate={API_UPDATE_DATA_COUNTRY}
urlParamDelete={API_DELETE_DATA_COUNTRY}
/>
</div>
)
}
}
export default MasterCountry;

6
src/views/Master/MasterCountry/package.json

@ -1,6 +0,0 @@
{
"name": "MasterCountry",
"version": "0.0.0",
"private": true,
"main": "./MasterCountry.js"
}

156
src/views/Master/MasterGroupSales/DialogForm.js

@ -1,156 +0,0 @@
import React, { Component } from 'react'
import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
import { Col, Row, Button, Form, FormGroup, Label, Input } from 'reactstrap';
import { NotificationContainer, NotificationManager } from 'react-notifications';
import axios from 'axios'
const BASE_URL = "https://oslog.id/geohr-api/";
const formState = {
dataTable: [],
openDialog: false,
name: '',
description: '',
id: 0,
idData: 0,
nameMessage: "",
}
const ERROR_NAME = "name cannot be empty"
export default class DialogForm extends Component {
state = {
...formState
}
componentDidUpdate(prevProps, prevState) {
const { dataEdit, methodAct } = this.props
if ((prevProps.dataEdit !== dataEdit) && (methodAct == "Edit" || methodAct == "View")) {
this.setState({
idData: dataEdit.id,
name: dataEdit.name,
description: dataEdit.description,
})
}
}
handleSave = async () => {
const err = this.handleValidation();
let url = BASE_URL + "group-sales/add"
const { name, description, idData } = this.state
const { methodAct } = this.props
console.log(`methodAct`, methodAct)
if (methodAct === "Add") {
if (!err) {
const payload = {
name,
description,
}
const result = await axios.post(url, payload)
.then(res => res)
.catch((error) => error.response);
console.log(`result`, result)
if (result.data.message === "OK") {
this.props.closeDialog()
this.setState({
...formState,
})
NotificationManager.success('Data group sales berhasil ditambahkan!!', 'Success!!');
} else {
NotificationManager.error(result.data.message);
}
}
} else if (methodAct === "Edit") {
if (!err) {
let urlEdit = BASE_URL + `group-sales/${idData}/edit`;
const payload = {
name,
description,
}
const result = await axios.put(urlEdit, payload)
.then(res => res)
.catch((error) => error.response);
console.log(`result edit`, result)
if (result.data.message === "OK") {
this.props.closeDialog()
this.setState({
...formState,
})
NotificationManager.success('Data group sales berhasil diedit!!', 'Success!!');
} else {
NotificationManager.error(result.data.message);
}
}
}
}
handleCancel = () => {
this.props.closeDialog()
this.setState({
...formState
})
}
handleValidation = () => {
const { name } = this.state
let isError = false;
const errors = {
nameMessage: "",
}
if (name === "") {
isError = true
errors.nameMessage = ERROR_NAME
}
this.setState({
nameMessage: "",
...errors,
});
return isError;
}
renderForm = () => {
const { name, description, nameMessage } = this.state
return (
<Row form>
<Col md={12}>
<FormGroup>
<Label for="exampleEmail">Name</Label>
<Input type="text" value={name} onChange={
(e) => this.setState({
name: e.target.value,
nameMessage: e.target.value !== "" ? "" : ERROR_NAME
})} placeholder="name" invalid={nameMessage} />
</FormGroup>
</Col>
<Col md={12}>
<FormGroup>
<Label>Description</Label>
<Input type="text" value={description} onChange={(e) => this.setState({ description: e.target.value })} placeholder="description " />
</FormGroup>
</Col>
</Row>
)
}
render() {
const { openDialog, closeDialog, methodAct } = this.props
return (
<Modal isOpen={openDialog} toggle={openDialog} size="md">
<ModalHeader toggle={closeDialog}>{methodAct} Group Sales</ModalHeader>
<ModalBody>
<Form>
{this.renderForm()}
</Form>
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={this.handleSave}>{methodAct}</Button>{' '}
<Button color="secondary" onClick={this.handleCancel}>Cancel</Button>
</ModalFooter>
</Modal>
)
}
}

291
src/views/Master/MasterGroupSales/index.js

@ -1,291 +0,0 @@
import React, { Component } from 'react';
import { Card, CardBody, CardHeader, Col, Row, Table, Input, InputGroupButtonDropdown, DropdownToggle, DropdownItem, DropdownMenu, InputGroup } from 'reactstrap';
import BootstrapTable from 'react-bootstrap-table-next';
import { Button } from 'reactstrap';
import axios from 'axios';
import SweetAlert from 'react-bootstrap-sweetalert';
import DialogForm from './DialogForm';
import paginationFactory from 'react-bootstrap-table2-paginator';
import { NotificationContainer, NotificationManager } from 'react-notifications';
import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
import { Pagination } from 'antd';
import { Tooltip } from 'reactstrap';
const BASE_URL = "https://oslog.id/geohr-api/";
const { SearchBar } = Search;
const NoDataIndication = () => (
<div className="spinner">
<div className="rect1" />
<div className="rect2" />
<div className="rect3" />
</div>
);
const column = [
{ name: "Name" },
{ name: "Description" },
]
const LENGTH_DATA = 10
export default class index extends Component {
constructor(props) {
super(props)
this.state = {
data: [],
openDialog: false,
typeDialog: 'Save',
dataEdit: null,
alertDelete: false,
idDelete: 0,
search: "",
alert: false,
methodAct: "Add",
page: 0,
totalPage: 0,
rowsPerPage: LENGTH_DATA,
currentPage: 1,
splitButtonOpen: false,
searchDetail: "All",
searchDetailField: "name",
tooltipDelete: false,
tooltipEdit: false
}
}
async componentDidMount() {
const { page, rowsPerPage } = this.state
this.getDataGroupSales(page, rowsPerPage);
}
async componentDidUpdate(prevProps, prevState) {
const { search, rowsPerPage, page } = this.state
if (page !== prevState.page) {
this.getDataGroupSales(page, rowsPerPage)
}
if (rowsPerPage !== prevState.rowsPerPage) {
this.getDataGroupSales(0, rowsPerPage)
this.setState({ page: 0 })
}
if (search !== prevState.search) {
this.getDataGroupSales(0, rowsPerPage)
this.setState({ page: 0 })
}
};
handleSearch = e => {
const value = e.target.value
this.setState({ search: value, page: 0 })
};
getDataGroupSales = async (start, length) => {
const { search, rowsPerPage, searchDetail, searchDetailField } = this.state
let url = BASE_URL + "group-sales/search";
const obj = {
"paging": { "start": start, "length": length },
...searchDetail === "All" &&
{
"filter_columns": [
{ "name": "name", "value": search.toString() },
{ "name": "description", "value": search.toString() },
],
},
...searchDetail !== "All" &&
{
"columns": [
{ "name": searchDetailField, "logic_operator": "ilike", "operator": "and", "value": search.toString() }
]
},
"orders": { "columns": ["created_date"], "ascending": false }
}
const result = await axios
.post(url, obj)
.then(res => res)
.catch((error) => error.response);
if (result.data.message == "OK") {
console.log(`result data`, result.data.data)
this.setState({ data: result.data.data, totalPage: result.data.totalRecord });
} else {
NotificationManager.error('Failed retreiving data!!', 'Failed');
}
}
handleOpenDialog = () => {
this.setState({ openDialog: true, methodAct: "Add" })
}
handleCloseDialog = () => {
this.setState({ openDialog: false })
this.getDataGroupSales()
}
handleEditData = (data) => {
this.setState({ dataEdit: data, openDialog: true, methodAct: "Edit" })
}
onDelete = (id) => {
this.setState({
alertDelete: true,
idDelete: id
})
}
handleDeleted = async (param) => {
const { idDelete } = this.state
if (param === "delete") {
const result = await axios.delete(`${BASE_URL}/group-sales/${idDelete}/delete`)
.then((response) => response)
.catch((error) => error.response)
this.setState({
alertDelete: false,
alert: true
})
await this.getDataGroupSales()
} else {
this.setState({
alertDelete: false
})
}
}
onShowSizeChange = (current, pageSize) => {
this.setState({ rowsPerPage: pageSize })
}
onPagination = (current, pageSize) => {
this.setState({ currentPage: current, page: (current - 1) * pageSize })
}
toggleDropDown = () => {
this.setState(prevState => ({ splitButtonOpen: !prevState.splitButtonOpen }))
}
toggle = (param) => {
if (param === "edit") {
this.setState(prevState => ({ tooltipEdit: !prevState.tooltipEdit }))
} else if (param === "delete") {
this.setState(prevState => ({ tooltipDelete: !prevState.tooltipDelete }))
}
}
render() {
const { openDialog, data, search, alert, page, totalPage, rowsPerPage, currentPage, searchDetail, searchDetailField, splitButtonOpen, tooltipEdit, tooltipDelete } = this.state
let noSeq = 0;
return (
<div>
<NotificationContainer />
<SweetAlert show={alert} success title="deleted successfully!" onConfirm={() => this.setState({ alert: false })} onCancel={() => this.setState({ alert: false })}>
You clicked the button!
</SweetAlert>
<SweetAlert
show={this.state.alertDelete}
warning
showCancel
confirmBtnText="Delete"
confirmBtnBsStyle="danger"
title="Are you sure?"
onConfirm={() => this.handleDeleted("delete")}
onCancel={() => this.handleDeleted("cancel")}
focusCancelBtn
>
Data group sales akan terhapus!!
</SweetAlert>
<DialogForm
openDialog={openDialog}
closeDialog={this.handleCloseDialog}
dataEdit={this.state.dataEdit}
methodAct={this.state.methodAct}
/>
<Card>
<CardHeader style={{ display: "flex", justifyContent: "space-between" }}>
<h4>Group Sales</h4>
<Button color="primary" onClick={() => this.handleOpenDialog('Save')}>Add Group Sales</Button>
</CardHeader>
<CardBody>
<InputGroup style={{ maxWidth: "200px", marginBottom: "20px" }}>
<Input onChange={this.handleSearch} value={search} type="text" name="search" id="search" placeholder={`Search ${searchDetail}`} />
<InputGroupButtonDropdown addonType="prepend"
isOpen={splitButtonOpen}
toggle={this.toggleDropDown}
>
<DropdownToggle split outline />
<DropdownMenu>
<DropdownItem onClick={
() => this.setState({
searchDetail: "All",
searchDetailField: "name"
})}>All</DropdownItem>
<DropdownItem onClick={
() => this.setState({
searchDetail: "Name",
searchDetailField: "name"
})}>Name</DropdownItem>
<DropdownItem onClick={
() => this.setState({
searchDetail: "Description",
searchDetailField: "description"
})}>Description</DropdownItem>
</DropdownMenu>
</InputGroupButtonDropdown>
</InputGroup>
<Table responsive striped hover>
<thead>
<tr>
<th>Actions</th>
{column.map((i) => {
return (
<th scope="row">{i.name}</th>
)
})}
</tr>
</thead>
<tbody>
{data.map((n) => {
return (
<tr key={n.id}>
<td>
{/* delete */}
<i id="TooltipDelete" class="cil-trash fa-lg" style={{ color: 'red', marginRight: '10px', cursor: "pointer" }} onClick={() => this.onDelete(n.id)}></i>
<Tooltip placement="right" isOpen={tooltipDelete} target="TooltipDelete" toggle={() => this.toggle("delete")}>
Delete
</Tooltip>
{/* edit */}
<i id="TooltipEdit" class="cil-pencil fa-lg" style={{ color: 'green', cursor: "pointer", marginRight: '10px', }} onClick={() => this.handleEditData(n)}></i>
<Tooltip placement="right" isOpen={tooltipEdit} target="TooltipEdit" toggle={() => this.toggle("edit")}>
Edit
</Tooltip>
{/* <i class="cil-search fa-lg" style={{ color: 'blue', cursor: "pointer" }} onClick={() => this.handleDetail(n)}></i> */}
</td>
<td>{n.name}</td>
<td>{n.description}</td>
</tr>
)
})}
</tbody>
</Table>
<Pagination
showSizeChanger
onShowSizeChange={this.onShowSizeChange}
onChange={this.onPagination}
defaultCurrent={currentPage}
pageSize={rowsPerPage}
total={totalPage}
pageSizeOptions={["10", "15", "20", "25", "30", "35", "40"]}
/>
</CardBody>
</Card>
</div>
)
}
}

581
src/views/Master/MasterKaryawan/DialogForm.js

@ -1,581 +0,0 @@
import React, { Component } from 'react'
import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
import { Col, Row, Button, Form, FormGroup, Label, Input, FormText } from 'reactstrap';
import Select from 'react-select'
import axios from 'axios';
import moment from 'moment';
import { DatePicker } from 'antd';
import 'antd/dist/antd.css';
import { BASE_URL_GEOHR_API2 } from '../../../const/ApiConst'
import '../MasterDataStyles.css'
import SweetAlert from 'react-bootstrap-sweetalert';
import { NotificationContainer, NotificationManager } from 'react-notifications';
const format = 'YYYY-MM-DD';
let countError = 0;
const listGender = [
{
"value": "L",
"label": "Laki-laki"
},
{
"value": "P",
"label": "Perempuan"
}]
const listBlood = [
{
"value": "A",
"label": "A"
},
{
"value": "AB",
"label": "AB"
},
{
"value": "B",
"label": "B"
},
{
"value": "O",
"label": "O"
}]
const API = `https://oslog.id/geohr-api`
export default class DialogForm extends Component {
constructor(props) {
super(props)
this.state = {
id: 0,
idDivision:0,
idRoles:0,
name:"",
email:"",
phoneNumber:"",
username:"",
password:"",
address:"",
birthPlace: "",
birthDate: null,
currentSelectGender: null,
hobby: "",
openDialog: false,
isParentClick: false,
currentSelectVal: null,
dataDivision:[],
listDivisionSelect:[],
selectDisable: false,
dataRoles:[],
listRolesSelect:[],
selectDisableRoles: false,
currentSelectRoles: null,
currentSelectBlood: null,
selectDisableBlood: false,
nik: "",
files: [],
showImg: false,
getUrl: "",
namePhoto: "",
alertDelete: false,
idDelete: 0 ,
dataPhoto: null
}
}
fileSelectedHandler = (e) => {
this.setState({ files: [...this.state.files, ...e.target.files] }, () => {
console.log('test data foto', this.state.files)
})
}
async componentDidMount(){
this.getDataRoles()
this.props.showDialog(this.showDialog);
}
async componentDidUpdate (prevProps, prevState){
const { dataEdit } = this.props
if(this.state.isParentClick===true){
if(this.props.typeDialog==="Edit" || this.props.typeDialog==="View"){
if(dataEdit.role_id!=="" && dataEdit.role_id!==null && dataEdit.role_id!==undefined){
this.searchRoles(dataEdit.role_id);
}
this.getUrlImagery(dataEdit.id)
this.setState({
id:dataEdit.id,
idRoles: dataEdit.role_id,
idDivision:dataEdit.employee_division_id,
username:dataEdit.username || "",
name:dataEdit.name || "",
email:dataEdit.email || "",
password:"",
phoneNumber:dataEdit.phone_number || "",
address:dataEdit.address || "",
birthPlace: dataEdit.birth_place || "",
birthDate: dataEdit.birth_date || null,
currentSelectGender: dataEdit.gender ? listGender.find((x) => x.value === dataEdit.gender) : null,
hobby: dataEdit.hobby || "",
nik: dataEdit.ktp_number || "",
currentSelectBlood: dataEdit.blood_type ? listBlood.find((x) => x.value === dataEdit.blood_type) : null,
})
}else{
this.setState({
id:0,
idDivision:0,
idRoles:0,
name:"",
email:"",
password:"",
phoneNumber:"",
address:"",
username:"",
birthPlace: "",
birthDate: null,
currentSelectGender: null,
hobby: "",
currentSelectVal:null,
currentSelectRoles:null,
nik: "",
currentSelectBlood: null,
files: []
})
}
this.setState({isParentClick:false});
}
}
closeImg = () => {
this.setState({ showImg: false })
}
getUrlImagery = async (param) => {
const payload = {
"paging": { "start": 0, "length": -1 },
"columns": [
{ "name": "category", "logic_operator": "=", "value": "employee", "operator": "and" },
{ "name": "ref_id", "logic_operator": "=", "value": param.toString(), "operator": "and" }
],
"orders": { "columns": ["id"], "ascending": true }
}
const resultUrl = await axios.post(`${API}/image/search`, payload).then(response => response).catch(err => err.response)
this.setState({ files: resultUrl.data.data })
console.log(`resultUrl`, resultUrl.data.data)
}
getDataDivision = async () => {
countError++;
let url = BASE_URL_GEOHR_API2+`/employee_devision.php?act=get_data`;
const result = await axios
.get(url)
.then(res => res)
.catch((error) => error.response );
console.log('cek', result)
if(result && result.data && result.data.code_status === 200){
this.setState({ dataDivision:result.data.data },()=>{
this.setDataDivision();
})
}else{
if(countError<6){
this.getDataDivision();
}
}
}
getDataRoles = async () => {
countError++;
let url = BASE_URL_GEOHR_API2+`/roles.php?act=get_data`;
const result = await axios
.get(url)
.then(res => res)
.catch((error) => error.response );
console.log('cek', result)
if(result && result.data && result.data.code_status === 200){
this.setState({ dataRoles:result.data.data },()=>{
this.setDataRoles();
})
}else{
if(countError<6){
this.getDataRoles();
}
}
}
setDataDivision = () => {
const { dataDivision } = this.state
const listDivision = []
dataDivision.map((val, index)=> {
listDivision.push({
value:val.id,
label:val.name
})
})
this.setState({ listDivisionSelect:listDivision })
}
setDataRoles = () => {
const { dataRoles } = this.state
const listRoles = []
dataRoles.map((val, index)=> {
listRoles.push({
value:val.id,
label:val.name
})
})
this.setState({ listRolesSelect:listRoles })
}
searchDivision = (id) => {
let getIndex = this.getIndexDataDivision(id);
let data = this.state.dataDivision[getIndex]
this.setState({ idDivision:data.id,currentSelectVal:{value:data.id,label:data.name} })
}
getIndexDataDivision = (val) => {
let index = this.state.dataDivision.findIndex(obj => obj.id === val);
return index
}
searchRoles = (id) => {
let getIndex = this.getIndexDataRoles(id);
let data = this.state.dataRoles[getIndex]
this.setState({ idRoles:data.id,currentSelectRoles:{value:data.id,label:data.name} })
}
getIndexDataRoles = (val) => {
let index = this.state.dataRoles.findIndex(obj => obj.id === val);
return index
}
showDialog = () => {
this.setState({ isParentClick : true });
}
handleDeletePhoto = (data) => {
this.setState({ alertDelete: true, dataPhoto: data }, () => {
console.log('data photo', this.state.dataPhoto)
});
}
handleSave = async () => {
const {
id,
idDivision,
username,
name,
email,
password,
address,
phoneNumber,
idRoles,
birthPlace,
birthDate,
currentSelectGender,
hobby,
currentSelectBlood,
nik,
files,
currentSelectRoles
} = this.state
let data = '';
if(this.props.typeDialog==="Save"){
data = {
idDivision,
username,
name,
email,
password,
address,
phoneNumber,
idRoles,
birthPlace,
birthDate,
currentSelectGender,
hobby,
nik,
currentSelectBlood,
files,
currentSelectRoles
}
this.props.closeDialog('save', data);
}else{
data = {
id,
username,
name,
email,
password,
address,
phoneNumber,
idDivision,
idRoles,
birthPlace,
birthDate,
currentSelectGender,
hobby,
nik,
currentSelectBlood,
currentSelectRoles
}
console.log('test log data', data)
if (files.length > 0) {
const formData = new FormData()
files.map((res) => {
if (res)
formData.append("ref_id", id);
formData.append("files", res);
})
await axios.post(`${API}/image/employee/upload`, formData).then(response => response).catch(err => err.response)
}
this.props.closeDialog('edit', data);
}
this.setState({ id:0,idDivision:0,currentSelectVal:null, currentSelectRoles: null, currentSelectGender: null, currentSelectBlood: null });
}
handleCancel = () => {
this.setState({ id:0,currentSelectVal:null, currentSelectRoles: null, currentSelectGender: null, currentSelectBlood: null });
this.props.closeDialog('cancel', 'none')
}
handleSelectGs = (inputValue, actionMeta) => {
this.setState({ idDivision:inputValue.value,currentSelectVal:{ value:inputValue.value,label:inputValue.label } })
}
handleSelectRoles = (inputValue, actionMeta) => {
this.setState({ idRoles:inputValue.value,currentSelectRoles:{ value:inputValue.value,label:inputValue.label } }, ()=> {
console.log("test select role", this.state.currentSelectRoles)
})
}
onConfirmDeletePhoto = async () => {
const { id, dataPhoto } = this.state
let url = `https://oslog.id/geohr-api/image/employee/${id}/delete?files=${dataPhoto.image}`
let result = await axios.delete(url)
.then(res => res)
.catch((error) => error.response);
if(result.message!==undefined){
}else{
}
console.log("test data photooo", result)
if (result) {
this.getUrlImagery(id)
this.setState({ dataPhoto: null, alertDelete: false })
NotificationManager.success('Foto berhasil dihapus!!', 'Success!!');
} else {
this.getUrlImagery(id)
this.setState({ dataPhoto: null, alertDelete: false })
NotificationManager.error('Foto gagal dihapus!!', 'Failed!!');
}
}
renderForm = () => {
const {files} = this.state
const {typeDialog} = this.props
let typeRole = localStorage.getItem('role_name')
return(
<Form>
<Row>
<Col md={6} xs={12}>
{/* <FormGroup>
<Label className="formLabel">Divisi</Label>
<Select options={this.state.listDivisionSelect} onChange={this.handleSelectGs} value={this.state.currentSelectVal} isDisabled={typeDialog === "View"} />
</FormGroup> */}
<Row>
<Col md={6} xs={6}>
<FormGroup>
<Label className="formLabel">Nama Pengguna</Label>
<Input readOnly={typeDialog === "View"} type="text" value={this.state.username} onChange={(e) => this.setState({username:e.target.value})} placeholder="" />
</FormGroup>
</Col>
<Col md={6} xs={6}>
<FormGroup>
<Label className="formLabel">Kata Sandi</Label>
<Input readOnly={typeDialog === "View"} type="password" value={this.state.password} onChange={(e) => this.setState({password:e.target.value})} placeholder="" />
{this.props.typeDialog==="Save" ? "" : <p>*Kosongkan jika tidak ada perubahaan</p>}
</FormGroup>
</Col>
</Row>
<FormGroup>
<Label className="formLabel">NIK (KTP)</Label>
<Input readOnly={typeDialog === "View"} type="text" value={this.state.nik} onChange={(e) => this.setState({nik:e.target.value})} placeholder="" />
</FormGroup>
<FormGroup>
<Label className="formLabel">Nama</Label>
<Input readOnly={typeDialog === "View"} type="text" value={this.state.name} onChange={(e) => this.setState({name:e.target.value})} placeholder="" />
</FormGroup>
<FormGroup>
<Label className="formLabel">Email</Label>
<Input readOnly={typeDialog === "View"} type="email" value={this.state.email} onChange={(e) => this.setState({email:e.target.value})} placeholder="" />
</FormGroup>
<FormGroup>
<Label className="formLabel">Nomor Telepon</Label>
<Input readOnly={typeDialog === "View"} type="number" value={this.state.phoneNumber} onChange={(e) => this.setState({phoneNumber:e.target.value})} placeholder="" />
</FormGroup>
<FormGroup>
{typeDialog !== "View" && (
<>
<Label for="exampleFile">File</Label>
<Input type="file" name="file" id="exampleFile" multiple onChange={this.fileSelectedHandler} />
<FormText>Max Size 1Mb</FormText>
</>
)}
{files && (
<div style={{ maxHeight: "300px", maxWidth: "100%", overflowY: "auto",display: "flex", flexDirection: "row" }}>
{files.map((item) => {
let checkImg = null
if (item.image) {
checkImg = `${API}/assets/images/employee/${item.image}`
} else {
checkImg = URL.createObjectURL(item)
}
return (
<div>
{typeDialog === "Edit" && (
<div onClick={() => this.handleDeletePhoto(item)} style={{cursor: "pointer", position: "absolute", width: 30, height: 30, borderRadius: 30 / 2, backgroundColor: "grey", marginTop: 10, marginLeft: 10, justifyContent: "center", alignContent: "center", paddingTop: 4, paddingLeft: 5 }}>
<i className="cil-trash fa-lg" style={{ color: 'red'}}></i>
</div>
)
}
<img key={item.id} src={checkImg} alt="..." style={{ maxWidth: "150px", maxHeight: "150px" }} />
</div>
)
})}
</div>
)
}
</FormGroup>
</Col>
<Col md={6} xs={12}>
{typeRole === "Superadmin" && (
<FormGroup>
<Label className="formLabel">Roles</Label>
<Select options={this.state.listRolesSelect} onChange={this.handleSelectRoles} value={this.state.currentSelectRoles} isDisabled={typeDialog === "View"} />
</FormGroup>
)
}
<FormGroup>
<Label className="formLabel">Jenis Kelamin</Label>
<Select options={listGender} onChange={(inputValue, actionMeta) => this.setState({currentSelectGender: {value: inputValue.value, label: inputValue.label}})} value={this.state.currentSelectGender} isDisabled={typeDialog === "View"} />
</FormGroup>
<FormGroup style={{ marginTop: 30 }}>
<Label className="formLabel">Golongan Darah</Label>
<Select options={listBlood} onChange={(inputValue, actionMeta) => this.setState({currentSelectBlood: {value: inputValue.value, label: inputValue.label}})} value={this.state.currentSelectBlood} isDisabled={typeDialog === "View"} />
</FormGroup>
<Row>
<Col md={6} xs={12}>
<FormGroup>
<Label className="formLabel">Tempat Lahir</Label>
<Input readOnly={typeDialog === "View"} type="text" value={this.state.birthPlace} onChange={(e) => this.setState({birthPlace:e.target.value})} placeholder="" />
</FormGroup>
</Col>
<Col md={6} xs={12}>
<FormGroup>
<Label className="formLabel">Tanggal Lahir</Label>
<Row>
<Col md={12}>
<DatePicker disabled={typeDialog === "View"} style={{width: "100%"}} onChange={(e, val) => this.setState({birthDate: val})} defaultValue={this.state.birthDate ? moment(this.state.birthDate, format) : null} />
</Col>
</Row>
</FormGroup>
</Col>
</Row>
<FormGroup>
<Label className="formLabel">Alamat</Label>
<Input readOnly={typeDialog === "View"} type="text" value={this.state.address} onChange={(e) => this.setState({address:e.target.value})} placeholder="" />
</FormGroup>
<FormGroup>
<Label className="formLabel">Hobby</Label>
<Input readOnly={typeDialog === "View"} type="text" value={this.state.hobby} onChange={(e) => this.setState({hobby:e.target.value})} placeholder="" />
</FormGroup>
</Col>
</Row>
</Form>
)
}
render() {
const {typeDialog} = this.props
return (
<Modal size="xl" isOpen={this.props.openDialog} toggle={this.props.toggleDialog}>
<NotificationContainer />
<SweetAlert
show={this.state.alertDelete}
warning
showCancel
confirmBtnText="Delete"
confirmBtnBsStyle="danger"
title="Are you sure?"
onConfirm={this.onConfirmDeletePhoto}
onCancel={() => this.setState({ alertDelete: false, dataPhoto: null})}
focusCancelBtn
>
Foto Akan Terhapus!!
</SweetAlert>
<ModalHeader toggle={() => this.handleCancel()}>{this.props.typeDialog} Karyawan</ModalHeader>
<ModalBody>
{this.renderForm()}
</ModalBody>
{typeDialog !== "View" && (
<ModalFooter>
<Button color="primary" onClick={() => this.handleSave()}>{this.props.typeDialog}</Button>{' '}
<Button color="secondary" onClick={() => this.handleCancel()}>Cancel</Button>
</ModalFooter>
)}
</Modal>
)
}
}

79
src/views/Master/MasterKaryawan/DialogImport.js

@ -1,79 +0,0 @@
import React, { Component } from 'react'
import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
import { Col, Row, Button, Form, FormGroup, Label, Input } from 'reactstrap';
import moment from 'moment';
import 'antd/dist/antd.css';
export default class DialogImport extends Component {
constructor(props) {
super(props)
this.state = {
dataImport:null,
openDialog: false,
isParentClick: false,
disable: false
}
}
async componentDidMount(){
this.props.showDialog(this.showDialog);
}
async componentDidUpdate (){
if(this.state.isParentClick===true){
this.setState({isParentClick:false});
}
}
showDialog = () => {
this.setState({ isParentClick : true });
}
handleSave = () => {
const {
dataImport
} = this.state
this.props.closeDialog('import', dataImport);
this.setState({ dataImport:null });
}
handleCancel = () => {
this.props.closeDialog('cancel', 'none')
}
importExcel = (e) => {
e.preventDefault();
let file = e.target.files[0];
this.setState({dataImport:file});
}
renderForm = () => {
return(
<Form>
<FormGroup>
<Label>Excel</Label>
<Input type="file" onChange={this.importExcel} />
</FormGroup>
</Form>
)
}
render() {
return (
<Modal isOpen={this.props.openDialog} toggle={this.props.toggleDialog}>
<ModalHeader toggle={this.props.closeDialog}>Import Data Karyawan</ModalHeader>
<ModalBody>
{this.renderForm()}
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={() => this.handleSave()}>Import</Button>{' '}
<Button color="secondary" onClick={() => this.handleCancel()}>Cancel</Button>
</ModalFooter>
</Modal>
)
}
}

607
src/views/Master/MasterKaryawan/index.js

@ -1,607 +0,0 @@
import React, { Component } from 'react';
import { Card, CardBody, CardHeader, Col, Row, Table, Input,InputGroup, InputGroupButtonDropdown, DropdownToggle, DropdownItem, DropdownMenu,ButtonDropdown } from 'reactstrap';
import { Button } from 'reactstrap';
import axios from 'axios';
import moment from 'moment';
import SweetAlert from 'react-bootstrap-sweetalert';
import DialogForm from './DialogForm';
import DialogImport from './DialogImport';
import { NotificationContainer, NotificationManager } from 'react-notifications';
import { Pagination } from 'antd';
import { Tooltip } from 'reactstrap';
import * as XLSX from 'xlsx';
import { BASE_URL_GEOHR_API2 } from '../../../const/ApiConst'
import { Icon, InlineIcon } from '@iconify/react';
import eyeFilled from '@iconify/icons-ant-design/eye-filled';
import { Link } from 'react-router-dom';
const id_org = window.localStorage.getItem('id_org');
const roleName = window.localStorage.getItem('role_name');
const momentFormat = 'HH:mm';
const column = [
{ name: "Organasi" },
{ name: "Nama" },
{ name: "Email" },
{ name: "Nomor Handphone" },
]
const LENGTH_DATA = 10
const API = `https://oslog.id/geohr-api`
export default class index extends Component {
constructor(props) {
super(props)
this.state = {
dataTable: [],
finalData: [],
openDialog: false,
typeDialog: 'Save',
dataEdit: null,
alertDelete: false,
idDelete: 0,
dataGs: [],
dataIdHo: [],
search: "",
page: 0,
rowsPerPage: LENGTH_DATA,
currentPage: 1,
totalPage: 0,
tooltipEdit: false,
tooltipDelete: false,
splitButtonOpen:false,
searchDetail: "Nama",
searchDetailField: "name",
tooltipDetail: false,
tooltipTambah:false,
tooltipImport:false,
tooltipExport:false,
dataImport: null,
aksiDropdown:false,
openDialogImport:false,
dataExport:false,
}
}
async componentDidMount() {
this.getDataEmployee();
}
async componentDidUpdate(prevProps, prevState) {
const { search } = this.state
if (search !== prevState.search) this.getDataEmployee()
}
toggleAksiDropdown = () => {
this.setState({aksiDropdown:!this.state.aksiDropdown});
}
handleSearch = e => {
const value = e.target.value
this.setState({ search: value, currentPage: 1 })
};
getDataEmployee = async () => {
let start = 0;
if (this.state.currentPage !== 1) {
start = (this.state.currentPage * this.state.rowsPerPage) - this.state.rowsPerPage
}
let url = BASE_URL_GEOHR_API2 + `/employee.php?act=get_data&start=${start}&length=${this.state.rowsPerPage}&role_name=${roleName}`;
const formData = new FormData();
formData.append("id_org", id_org);
formData.append('field', this.state.searchDetailField);
formData.append('value', this.state.search);
const result = await axios
.post(url,formData)
.then(res => res)
.catch((error) => error.response);
if (result && result.data && result.statusText == "OK") {
this.setState({ dataTable: result.data.data, totalPage: result.data.total_record });
} else {
NotificationManager.error('Failed retreiving data!!', 'Failed');
}
}
setListIdHo = (data) => {
let list = [];
data.map((val, index) => {
list.push(val.sales)
})
this.setState({ dataIdHo: list }, () => {
})
}
handleOpenDialog = (type) => {
this.setState({ openDialog: true, typeDialog: type })
this.showChildDialog();
}
handleCloseDialog = async (type, data) => {
let result = false;
if (type === "save") {
result = await this.saveEmployee(data);
} else if (type === "edit") {
result = await this.editEmployee(data);
}
else if (type === "cancel") {
result = true;
}
if (result) {
this.setState({ openDialog: false })
}
}
toggleAddDialog = () => {
this.setState({ openDialog: !this.state.openDialog })
}
onConfirmDelete = async () => {
const { idDelete } = this.state
let url = BASE_URL_GEOHR_API2 + `/employee.php?act=delete&id=${idDelete}`;
let result = await axios.get(url)
.then(res => res)
.catch((error) => error.response);
if(result.message!==undefined){
}else{
}
if (result.data.message === "Data Has Been Deleted") {
this.getDataEmployee()
this.setState({ idDelete: 0, alertDelete: false })
NotificationManager.success('Data employee berhasil dihapus!!', 'Success!!');
} else {
this.setState({ idDelete: 0, alertDelete: false })
NotificationManager.error('Data employee gagal dihapus!!', 'Failed!!');
}
}
saveEmployee = async (data) => {
let url = BASE_URL_GEOHR_API2 + "/employee.php?act=input";
const formData = new FormData();
formData.append('name', data.name);
formData.append('username', data.username);
formData.append('phone_number', data.phoneNumber);
formData.append('email', data.email);
formData.append('address', data.name);
formData.append('password', data.password);
formData.append('birth_place', data.birthPlace);
formData.append('birth_date', data.birthDate);
formData.append('gender', data.currentSelectGender ? data.currentSelectGender.value : "");
formData.append('hobby', data.hobby);
formData.append('blood_type', data.currentSelectBlood ? data.currentSelectBlood.value: "");
formData.append('ktp_number', data.nik);
formData.append('role_id', data.currentSelectRoles ? data.currentSelectRoles.value: "");
if(data.idRoles!==undefined && data.idRoles!==0 && data.idRoles!==null){
formData.append('roles_id', data.idRoles);
}
let result = await axios.post(url, formData)
.then(res => res)
.catch((error) => error.response);
if (!result) {
return false;
}
if(result && result.message!==undefined){
if (result.message === "Data Has Been Saved") {
this.getDataEmployee();
NotificationManager.success('Data employee berhasil ditambahkan!!', 'Success!!');
return true;
} else {
NotificationManager.error(`${result.data.message}`, 'Failed!!');
return false;
}
}else{
if (result.data.message === "Data Has Been Saved") {
this.getDataEmployee();
NotificationManager.success('Data employee berhasil ditambahkan!!', 'Success!!');
return true;
} else {
NotificationManager.error(`${result.data.message}`, 'Failed!!');
return false;
}
}
let ref_id = parseInt(result.data.data.id)
if (ref_id) {
if (data.files.length > 0) {
const formData = new FormData()
data.files.map((res) => {
console.log('test data upload photo', res)
if (res)
formData.append("ref_id", ref_id);
formData.append("files", res);
})
await axios.post(`${API}/image/employee/upload`, formData).then(response => response).catch(err => err.response)
}
}
}
editEmployee = async (data) => {
let url = BASE_URL_GEOHR_API2 + `/employee.php?act=edit&id=${data.id}&role_name=${roleName}`;
const formData = new FormData();
formData.append('name', data.name);
formData.append('username', data.username);
formData.append('phone_number', data.phoneNumber);
formData.append('email', data.email);
formData.append('address', data.address);
formData.append('birth_place', data.birthPlace);
formData.append('birth_date', data.birthDate);
formData.append('gender', data.currentSelectGender ? data.currentSelectGender.value : "");
formData.append('hobby', data.hobby);
formData.append('blood_type', data.currentSelectBlood ? data.currentSelectBlood.value: "");
formData.append('role_id', data.currentSelectRoles ? data.currentSelectRoles.value: "");
formData.append('ktp_number', data.nik);
if(data.password!==""){
formData.append('password', data.password);
}
if(data.idRoles!==undefined && data.idRoles!==0 && data.idRoles!==null){
formData.append('role_id', data.idRoles);
}
let result = await axios.post(url, formData)
.then(res => res)
.catch((error) => error.response);
if (!result) {
return false;
}
if(result && result.message!==undefined){
if (result.message === "Data Has Been Edited") {
this.getDataEmployee();
NotificationManager.success('Data karyawan berhasil diedit!!', 'Success!!');
return true;
} else {
NotificationManager.error('Data karyawan gagal diedit!!', 'Failed!!');
return false
}
}else{
if (result.data.message === "Data Has Been Edited") {
this.getDataEmployee();
NotificationManager.success('Data karyawan berhasil diedit!!', 'Success!!');
return true;
} else {
NotificationManager.error('Data karyawan gagal diedit!!', 'Failed!!');
return false;
}
}
}
handleEdit = (data) => {
this.setState({ dataEdit: data });
this.handleOpenDialog('Edit');
}
handleDetail = (data) => {
this.setState({ dataEdit: data })
this.handleOpenDialog('View');
}
handleDelete = (id) => {
this.setState({ alertDelete: true, idDelete: id });
}
onShowSizeChange = (current, pageSize) => {
this.setState({ rowsPerPage: pageSize }, () => {
this.getDataEmployee();
})
}
onPagination = (current, pageSize) => {
this.setState({ currentPage: current, page: (current - 1) * pageSize }, () => {
this.getDataEmployee();
})
}
toggle = (param) => {
if (param === "edit") {
this.setState(prevState => ({ tooltipEdit: !prevState.tooltipEdit }))
} else if (param === "delete") {
this.setState(prevState => ({ tooltipDelete: !prevState.tooltipDelete }))
} else if (param === "detail") {
this.setState(prevState => ({ tooltipDetail: !prevState.tooltipDetail }))
} else if (param === "tambah") {
this.setState(prevState => ({ tooltipTambah: !prevState.tooltipTambah }))
} else if (param === "import") {
this.setState(prevState => ({ tooltipImport : !prevState.tooltipImport }))
} else if (param === "export") {
this.setState(prevState => ({ tooltipExport: !prevState.tooltipExport }))
}
}
toggleDropDown = () => {
this.setState({splitButtonOpen:!this.state.splitButtonOpen})
}
handleDialogImport = () => {
this.setState({ openDialogImport: true})
this.showImportDialog();
}
handleCloseImport = (type, file) => {
if(type==="import"){
if(!file){
NotificationManager.error('Silahkan masukan file excel!!', 'Failed!!');
return false
}
if (/\.(xls?x)$/i.test(file.name) === false ) {
NotificationManager.error('File yang dimasukan bukan format excel (.xsl/.xslx)!!', 'Failed!!');
return false
}
this.importExcel(file);
}else{
this.setState({ openDialogImport:false });
}
}
toggleImportDialog = () => {
this.setState({ openDialogImport:!this.state.openDialogImport })
}
importExcel = async (file) => {
const url = `${BASE_URL_GEOHR_API2}/employee.php?act=import`;
const formData = new FormData();
formData.append('file', file);
const result = await axios
.post(url, formData)
.then((res) => res)
.catch((error) => error.response);
if(result && result.code_status){
if (result.code_status === 200) {
NotificationManager.success('File imported successfully', 'Success Message');
this.getDataEmployee();
this.setState({openDialogImport: false});
} else {
NotificationManager.error(result.data.message, "error message");
}
}else{
NotificationManager.error("Import data karyawan gagal!!", "error message");
}
}
getTemplateExcel = async (event) => {
event.preventDefault();
const url = `${BASE_URL_GEOHR_API2}/dok/template-import-karyawan.xlsx`;
window.open(url, "_blank");
};
handleExportExcel = async () => {
let start = 0;
let end = "ALL";
let url = BASE_URL_GEOHR_API2 + `/employee.php?act=get_data&start=${start}&length=${end}&role_name=${roleName}`;
const formData = new FormData();
formData.append('field', this.state.searchDetailField);
formData.append('value', this.state.search);
const result = await axios
.post(url,formData)
.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,
Organisasi:val.organization_name || "-",
Nik:val.ktp_number,
Username:val.username,
Email:val.email,
"Nomor Handphone":val.phone_number,
"Tanggal Lahir":val.birth_date,
"Tempat Lahir":val.birth_place,
"Hobby":val.hobby,
"Jenis Kelamin":val.gender,
"Golongan Data":val.blood_type,
}
dataExport.push(row);
})
this.setState({ dataExport:dataExport },()=> {
this.exportExcel();
});
} else {
NotificationManager.error('Failed retreiving data!!', 'Failed');
}
}
exportExcel = () => {
const dataExcel = this.state.dataExport || [];
const fileName = "Data Karyawan.xlsx";
const ws = XLSX.utils.json_to_sheet(dataExcel);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, 'Data Karyawan');
XLSX.writeFile(wb, fileName);
}
render() {
const { tooltipTambah,tooltipImport,tooltipExport,tooltipDetail, dataTable, searchDetail, splitButtonOpen, openDialog, currentPage, rowsPerPage, totalPage, search, tooltipEdit, tooltipDelete } = this.state
let dataTable2 = dataTable || [];
return (
<div>
<NotificationContainer />
<SweetAlert
show={this.state.alertDelete}
warning
showCancel
confirmBtnText="Delete"
confirmBtnBsStyle="danger"
title="Are you sure?"
onConfirm={this.onConfirmDelete}
onCancel={() => this.setState({ alertDelete: false, idDelete: 0 })}
focusCancelBtn
>
Data karyawan akan terhapus!!
</SweetAlert>
<DialogForm
openDialog={openDialog}
closeDialog={this.handleCloseDialog}
toggleDialog={() => this.toggleAddDialog}
typeDialog={this.state.typeDialog}
dataEdit={this.state.dataEdit}
showDialog={showDialog => this.showChildDialog = showDialog}
dataHs={this.state.dataIdHo}
/>
<DialogImport
openDialog={this.state.openDialogImport}
closeDialog={this.handleCloseImport}
toggleDialog={() => this.toggleImportDialog}
showDialog={showDialog => this.showImportDialog = showDialog}
/>
<Card>
<CardHeader style={{margin:0}}>
<Row style={{padding:0,margin:0}}>
<Col md={7} xs={7}>
<h4>Karyawan</h4>
</Col>
<Col md={3} xs={3}>
<InputGroup>
<Input onChange={this.handleSearch} value={search} type="text" name="search" id="search" placeholder={`Search ${searchDetail}`} />
<InputGroupButtonDropdown addonType="prepend"
isOpen={splitButtonOpen}
toggle={this.toggleDropDown}
>
<DropdownToggle split outline />
<DropdownMenu>
<DropdownItem onClick={
() => this.setState({
searchDetail: "Nama",
searchDetailField: "name"
})}>Nama</DropdownItem>
<DropdownItem onClick={
() => this.setState({
searchDetail: "Nomor Handphone",
searchDetailField: "phone_number"
})}>Nomor Handphone</DropdownItem>
<DropdownItem onClick={
() => this.setState({
searchDetail: "Email",
searchDetailField: "email"
})}>Email</DropdownItem>
<DropdownItem onClick={
() => this.setState({
searchDetail: "Alamat",
searchDetailField: "address"
})}>Alamat</DropdownItem>
</DropdownMenu>
</InputGroupButtonDropdown>
</InputGroup>
</Col>
<Col md={2} xs={2} style={{display:"flex",justifyContent:"space-between"}}>
<Button id="TooltipTambah" color="success" onClick={() => this.handleOpenDialog('Save')}><i className="fa fa-plus"></i></Button>
<ButtonDropdown id="TooltipImport" direction="down" isOpen={this.state.aksiDropdown} toggle={() => this.toggleAksiDropdown()}>
<DropdownToggle color="info" caret >
<i className="fa fa-cloud-upload"></i>
</DropdownToggle>
<DropdownMenu>
<DropdownItem onClick={() => this.handleDialogImport()}>Import Data Karyawan</DropdownItem>
<DropdownItem onClick={(e) => this.getTemplateExcel(e)}>Download Template</DropdownItem>
</DropdownMenu>
</ButtonDropdown>
<Button id="TooltipExport" color="primary" onClick={()=> this.handleExportExcel()}><i className="fa fa-print"></i></Button>
<Tooltip placement="right" isOpen={tooltipTambah} target="TooltipTambah" toggle={() => this.toggle("tambah")}>
Tambah
</Tooltip>
<Tooltip placement="right" isOpen={tooltipImport} target="TooltipImport" toggle={() => this.toggle("import")}>
Import Excel
</Tooltip>
<Tooltip placement="right" isOpen={tooltipExport} target="TooltipExport" toggle={() => this.toggle("export")}>
Export Excel
</Tooltip>
</Col>
</Row>
</CardHeader>
<CardBody>
<Table responsive striped hover>
<thead>
<tr>
<th>Aksi</th>
{column.map((i, index) => {
return (
<th key={index} scope="row">{i.name}</th>
)
})}
</tr>
</thead>
<tbody>
{dataTable2.map((n) => {
return (
<tr key={n.id}>
<td>
<i id="TooltipDelete" className="cil-trash fa-lg" style={{ color: 'red', marginRight: '10px', cursor: "pointer" }} onClick={() => this.handleDelete(n.id)}></i>
<Tooltip placement="right" isOpen={tooltipDelete} target="TooltipDelete" toggle={() => this.toggle("delete")}>
Hapus
</Tooltip>
<i id="TooltipEdit" className="cil-pencil fa-lg" style={{ color: 'green', cursor: "pointer" }} onClick={() => this.handleEdit(n)}></i>
<Tooltip placement="right" isOpen={tooltipEdit} target="TooltipEdit" toggle={() => this.toggle("edit")}>
Edit
</Tooltip>
<i id="TooltipDetail" style={{ marginLeft: 12, color: "blue", cursor: "pointer", }} onClick={() => this.handleDetail(n)}>
<Icon style={{ marginBottom: 6 }} color="blue" width={22} height={22} icon={eyeFilled} />
</i>
<Tooltip placement="right" isOpen={tooltipDetail} target="TooltipDetail" toggle={() => this.toggle("detail")}>
Detail
</Tooltip>
</td>
<td>{n.organization_name===null ? n.chairman_org || "-" : n.organization_name || "-"}</td>
<td>{n.name}</td>
<td>{n.email || "-"}</td>
<td>{n.phone_number || "-"}</td>
</tr>
)
})}
</tbody>
</Table>
<Pagination
showSizeChanger
onShowSizeChange={this.onShowSizeChange}
onChange={this.onPagination}
defaultCurrent={currentPage}
pageSize={rowsPerPage}
total={totalPage}
pageSizeOptions={["10", "15", "20", "25", "30", "35", "40"]}
/>
</CardBody>
</Card>
</div>
)
}
}

262
src/views/Master/MasterSales/DialogForm.js

@ -1,262 +0,0 @@
import React, { Component } from 'react'
import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
import { Col, Row, Button, Form, FormGroup, Label, Input } from 'reactstrap';
import Select from 'react-select'
export default class DialogForm extends Component {
constructor(props) {
super(props)
this.state = {
openDialog: false,
type_sales:'B2B',
name: '',
email: '',
address: '',
username: '',
phoneNumber: '',
password:'',
id: 0,
idGs:0,
isParentClick: false,
file: [],
fileObj: [],
fileArray: [],
dataGs: [],
currentSelectVal: null,
}
}
async componentDidMount(){
this.props.showDialog(this.showDialog);
this.cekDataGs()
}
async componentDidUpdate (){
if(this.state.isParentClick===true){
await this.cekDataGs()
if(this.props.typeDialog==="Edit"){
let dataGs = this.searchGs(this.props.dataEdit.group_sales);
this.setState({
idGs:this.props.dataEdit.group_sales,
id:this.props.dataEdit.id,
name:this.props.dataEdit.name,
type_sales:this.props.dataEdit.type_sales,
email: this.props.dataEdit.email,
address: this.props.dataEdit.address,
username: this.props.dataEdit.username,
phoneNumber: this.props.dataEdit.phone_number,
password:this.props.dataEdit.password,
currentSelectVal:dataGs
})
}else{
this.setState({
id:0,
name:'',
type_sales:'B2B',
email: '',
address:'',
username: '',
phoneNumber: '',
password: '',
currentSelectVal:null
})
}
this.setState({isParentClick:false});
}
}
searchGs = (idGs) => {
let getIndex = this.getIndexDataGs(idGs);
return this.state.dataGs[getIndex];
}
getIndexDataGs = (val) => {
let index = this.state.dataGs.findIndex(obj => obj.value === val);
return index
}
cekDataGs = () => {
if(this.state.dataGs.length===0){
let data = [];
this.props.dataGs.map((val,index) => {
data.push(
{
value: val.id,
label: val.name
}
)
});
this.setState({ dataGs:data })
}
}
showDialog = () => {
this.setState({ isParentClick : true });
}
handleSave = () => {
const { file, name, email, id, address, phoneNumber, password, username, idGs,type_sales } = this.state
let data = '';
if(this.props.typeDialog==="Save"){
data = {
username,
password,
name,
email,
address,
phone_number:phoneNumber,
group_sales:idGs,
type_sales
}
this.props.closeDialog('save', data, file);
}else{
data = {
id,
username,
password,
name,
email,
address,
phone_number:phoneNumber,
group_sales:idGs,
type_sales
}
this.props.closeDialog('edit', data, file);
}
this.setState({ id:'',username:'',password:'',name:'',email:'',address:'',phoneNumber:'',file:[],idGs:0,type_sales:'B2B',currentSelectVal:null });
}
handleCancel = () => {
this.setState({ id:'',username:'',password:'',name:'',email:'',address:'',phoneNumber:'',file:[],idGs:0,type_sales:'B2B' });
this.props.closeDialog('cancel', 'none', 'none')
}
uploadMultipleImage = (event) => {
this.setState({ fileObj: [...this.state.fileObj, event.target.files],file: [...this.state.file, event.target.files] }, ()=> {
this.setUrl()
})
}
setUrl = () => {
for (let i = 0; i < this.state.fileObj[0].length; i++) {
this.setState({ fileArray: [...this.state.fileArray, URL.createObjectURL(this.state.fileObj[0][i])],fileObj:[] })
}
}
handleSelectGs = (inputValue, actionMeta) => {
this.setState({ idGs:inputValue.value,currentSelectVal:{ value:inputValue.value,label:inputValue.label } })
}
handleTypeSales = (e) => {
this.setState({ type_sales:e.target.value })
}
renderForm = () => {
return(
<Form>
<Row form>
<Col md={6}>
<FormGroup>
<Label for="exampleEmail">Group Sales </Label>
<Select options={this.state.dataGs} onChange={this.handleSelectGs} value={this.state.currentSelectVal} />
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Label for="examplePassword">Username</Label>
<Input type="text" value={this.state.username} onChange={(e)=> this.setState({ username:e.target.value })} placeholder="username " />
</FormGroup>
</Col>
</Row>
<Row form>
<Col md={6}>
<FormGroup>
<Label for="exampleEmail">Password </Label>
<Input type="password" value={this.state.password} onChange={(e)=> this.setState({ password:e.target.value })} placeholder="password" />
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Label for="examplePassword">Name</Label>
<Input type="text" value={this.state.name} onChange={(e)=> this.setState({ name:e.target.value })} placeholder="name " />
</FormGroup>
</Col>
</Row>
<Row form>
<Col md={6}>
<FormGroup>
<Label for="exampleEmail">Email</Label>
<Input type="email" value={this.state.email} onChange={(e)=> this.setState({ email:e.target.value })} placeholder="email" />
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Label for="examplePassword">Address</Label>
<Input type="text" value={this.state.address} onChange={(e)=> this.setState({ address:e.target.value })} placeholder="address " />
</FormGroup>
</Col>
</Row>
<Row form>
<Col md={6}>
<FormGroup>
<Label for="exampleEmail">Phone Number</Label>
<Input type="number"value={this.state.phoneNumber} onChange={(e)=> this.setState({ phoneNumber:e.target.value })} placeholder="phone number" />
</FormGroup>
</Col>
<Col md={6}>
<Label>Type Sales</Label>
<Row>
<Col md={6}>
<FormGroup check>
<Label check>
<Input type="radio" name="radioTypeC" value="B2B" onChange={this.handleTypeSales} checked={this.state.type_sales==="B2B"} />{' '}
B2B
</Label>
</FormGroup>
</Col>
<Col md={6}>
<FormGroup check>
<Label check>
<Input type="radio" name="radioTypeC" value="B2C" onChange={this.handleTypeSales} checked={this.state.type_sales==="B2C"} />{' '}
B2C
</Label>
</FormGroup>
</Col>
</Row>
</Col>
</Row>
<FormGroup>
<div style={{overflowY:"auto "}}>
{(this.state.fileArray || []).map((url,index) => (
<img key={index} src={url} alt="..." style={{ maxWidth:"150px",maxHeight:"150px" }} />
))}
</div>
</FormGroup>
<FormGroup>
<Label for="exampleAddress">Images</Label>
<Input type="file" onChange={this.uploadMultipleImage} />
</FormGroup>
</Form>
)
}
render() {
return (
<Modal isOpen={this.props.openDialog} toggle={this.props.toggleDialog} size="xl">
<ModalHeader toggle={this.props.closeDialog}>Add Sales</ModalHeader>
<ModalBody>
{this.renderForm()}
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={() => this.handleSave()}>{this.props.typeDialog}</Button>{' '}
<Button color="secondary" onClick={() => this.handleCancel()}>Cancel</Button>
</ModalFooter>
</Modal>
)
}
}

347
src/views/Master/MasterSales/SettingSales.js

@ -1,347 +0,0 @@
import React, { Component } from 'react';
import { Card, CardBody, CardHeader, Col, Row, Table, Input, Modal, ModalHeader, ModalBody, ModalFooter, FormGroup, Label } from 'reactstrap';
import { Button } from 'reactstrap';
import axios from 'axios';
import SweetAlert from 'react-bootstrap-sweetalert';
import DialogForm from './DialogForm';
import { NotificationContainer, NotificationManager} from 'react-notifications';
import { Pagination } from 'antd';
import { Icon, InlineIcon } from '@iconify/react';
import settingOutlined from '@iconify/icons-ant-design/setting-outlined';
import {Link} from 'react-router-dom'
import Select from 'react-select'
import { SketchPicker } from 'react-color';
const BASE_URL = "https://oslog.id/geohr-api/";
const column = [
{ name: "Group Sales" },
{ name: "Name" },
{ name: "Phone Number" },
{ name: "Email" },
{ name: "Address" },
]
const layerSales = [
{
"id": 1,
"rule_name": "sales yang incomenya lebih dari 1000000",
"style": {
"fill_color": "#22194D",
},
"rule": {
"column": "income",
"operator": ">",
"value": 1000000,
}
},
{
"id": 2,
"rule_name": "sales yang punya nama mohammad",
"style": {
"fill_color": "#22194D",
},
"rule": {
"column": "name",
"operator": "like",
"value": "mohammad"
}
},
]
const options = [
{ value: 'group-sales', label: 'Group Sales' },
{ value: 'name', label: 'Name' },
{ value: 'phone-number', label: 'Phone Number' },
{ value: 'email', label: 'Email' },
{ value: 'address', label: 'Address' }
]
const logicOperator = [
{ value: '>', label: '>' },
{ value: '>=', label: '>=' },
{ value: '<', label: '<' },
{ value: '<=', label: '<=' },
{ value: '==', label: '==' },
{ value: '<>', label: '<>' },
]
const LENGTH_DATA = 10
export default class SettingSales extends Component {
constructor(props) {
super(props)
this.state = {
dataTable: [],
openDialog: false,
typeDialog: 'Save',
dataEdit: null,
alertDelete: false,
idDelete: 0,
dataGs: [],
search: "",
page: 0,
rowsPerPage: LENGTH_DATA,
currentPage: 1,
totalPage: 0,
layersSales: [],
modalEdit: false,
modalAdd: false,
id: 0,
fill_color: "#000",
column: "",
operator: "",
value: "",
dataEdit: null,
}
}
async componentDidMount (){
this.getRuleSales()
}
async componentDidUpdate (prevProps, prevState){
const { search } = this.state
if (search !== prevState.search) this.getRuleSales()
}
handleOpenDialog = (type) => {
this.setState({modalEdit: true, typeDialog: type })
this.handleSetData()
}
handleSetData = () => {
const { dataEdit, typeDialog} = this.state
if(typeDialog === "Edit") {
this.setState({
id: dataEdit.id,
rule_name: dataEdit.rule_name,
fill_color: dataEdit.style.fill_color,
column: dataEdit.rule.column,
value: dataEdit.rule.value,
operator: dataEdit.rule.operator
})
} else {
this.setState({
id: 0,
rule_name: "",
fill_color: "#000",
column: null,
value:"",
operator: null
})
}
}
handleEdit = (data) => {
this.setState({dataEdit: data})
this.handleOpenDialog('Edit')
console.log('test data edit', data)
}
handleCancel = () => {
this.setState({
rule_name: "",
fill_color: "#000",
column: null,
value:"",
operator: null,
modalEdit: false
})
}
handleSave = () => {
this.setState({
rule_name: "",
fill_color: "#000",
column: null,
value:"",
operator: null,
modalEdit: false })
}
toggleAdd = () => {
this.setState({modalAdd: !this.state.modalAdd})
}
getRuleSales = () => {
this.setState({layersSales: layerSales})
}
handleChangeComplete = (color, event) => {
console.log('handleChangeComplete',color, event);
this.setState({fill_color: color.hex});
}
render() {
const {layersSales, modalEdit, modalAdd, search, openDialog, currentPage, rowsPerPage,totalPage, dataTable } = this.state
let noSeq = 0;
return (
<div>
<NotificationContainer/>
<SweetAlert
show={this.state.alertDelete}
warning
showCancel
confirmBtnText="Delete"
confirmBtnBsStyle="danger"
title="Are you sure?"
onConfirm={()=> this.setState({ alertDelete:false })}
onCancel={()=> this.setState({ alertDelete:false })}
focusCancelBtn
>
Rule sales akan terhapus!!
</SweetAlert>
<Card>
<CardHeader style={{ display: "flex", justifyContent: "space-between" }}>
<h4>Rules Sales</h4>
<div>
<Button onClick={this.handleOpenDialog} color="primary" >Add Rule</Button>
</div>
</CardHeader>
<CardBody>
{layersSales.map((n) => {
return(
<Row key={n.id}>
<Col >
<Card className="layer-list">
<CardBody>
<Row>
<Col xs={2}>
<div style={{width: 20, height: 20, backgroundColor: n.style.fill_color }} />
</Col>
<Col xs={8} >
<span className="layer-title">{n.rule_name}</span>
</Col>
<Col >
<div style={{ flexDirection: "row", justifyContent: "flex-end", }}>
<Button onClick={()=> this.handleEdit(n)} color="success">Edit</Button>
<Button onClick={()=> this.setState({alertDelete: true})} style={{ marginLeft: 16 }} color="danger">Hapus</Button>
</div>
</Col>
</Row>
</CardBody>
</Card>
</Col>
</Row>
)
})
}
</CardBody>
</Card>
<Modal isOpen={modalEdit} toggle={this.handleCancel} >
<ModalHeader toggle={modalEdit}>Edit Rule Name</ModalHeader>
<ModalBody>
<div className="modal-body-container">
<FormGroup>
<Label>Layer Name</Label>
<Input value={this.state.rule_name} onChange={(e)=> this.setState({ rule_name :e.target.value })} />
</FormGroup>
<FormGroup>
<Label>Fill Color</Label>
<SketchPicker
color={ this.state.fill_color }
onChangeComplete={ this.handleChangeColorComplete }
/>
</FormGroup>
<FormGroup>
<Label>Rule</Label>
<Row>
<Col >
<Select value={this.state.column} options={options} />
</Col>
<Col>
<Select value={this.state.operator} options={logicOperator} />
</Col>
<Col >
<Input value={this.state.value} onChange={(e)=> this.setState({ value :e.target.value })} />
</Col>
</Row>
</FormGroup>
</div>
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={this.handleSave}>Update</Button>{' '}
<Button color="secondary" onClick={this.handleCancel}>Cancel</Button>
</ModalFooter>
</Modal>
{/* <Modal isOpen={modalAdd} toggle={this.toggleAdd} >
<ModalHeader toggle={modalEdit}>Add Rule Name</ModalHeader>
<ModalBody>
<div className="modal-body-container">
<FormGroup>
<Label>Rule Name</Label>
<Input />
</FormGroup>
<FormGroup>
<Label>Fill Color</Label>
<SketchPicker />
</FormGroup>
<FormGroup>
<Label>Rule</Label>
<Row>
<Col>
<Select options={options} />
</Col>
<Col>
<Select options={logicOperator} />
</Col>
<Col xs={5}>
<Input />
</Col>
</Row>
</FormGroup>
</div>
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={this.toggleAdd}>Save</Button>{' '}
<Button color="secondary" onClick={this.toggleAdd}>Cancel</Button>
</ModalFooter>
</Modal> */}
</div>
)
}
}

399
src/views/Master/MasterSales/index.js

@ -1,399 +0,0 @@
import React, { Component } from 'react';
import { Card, CardBody, CardHeader, Col, Row, Table, Input, InputGroup, InputGroupButtonDropdown, DropdownToggle, DropdownItem, DropdownMenu } from 'reactstrap';
import { Button } from 'reactstrap';
import axios from 'axios';
import SweetAlert from 'react-bootstrap-sweetalert';
import DialogForm from './DialogForm';
import { NotificationContainer, NotificationManager } from 'react-notifications';
import { Pagination } from 'antd';
import { Icon, InlineIcon } from '@iconify/react';
import settingOutlined from '@iconify/icons-ant-design/setting-outlined';
import { Link } from 'react-router-dom';
import { Tooltip } from 'reactstrap';
const BASE_URL = "https://oslog.id/geohr-api/";
const column = [
{ name: "Group Sales" },
{ name: "Name" },
{ name: "Phone Number" },
{ name: "Email" },
{ name: "Address" },
]
const LENGTH_DATA = 10
export default class index extends Component {
constructor(props) {
super(props)
this.state = {
dataTable: [],
openDialog: false,
typeDialog: 'Save',
dataEdit: null,
alertDelete: false,
idDelete: 0,
dataGs: [],
search: "",
page: 0,
rowsPerPage: LENGTH_DATA,
currentPage: 1,
totalPage: 0,
splitButtonOpen: false,
dropdownOpen: false,
searchDetail: "All",
searchDetailField: "name",
tooltipDelete: false,
tooltipEdit: false
}
}
async componentDidMount() {
this.getDataSales();
this.getDataGroupSales();
}
async componentDidUpdate(prevProps, prevState) {
const { search } = this.state
if (search !== prevState.search) this.getDataSales()
}
getDataGroupSales = async () => {
let url = BASE_URL + "group-sales/search";
const obj = {
"paging": { "start": 0, "length": -1 },
"columns": [
{
"name": "name",
"logic_operator": "ilike",
"value": "",
"operator": "and"
}
],
"orders": { "columns": ["name"], "ascending": true }
}
const result = await axios
.post(url, obj)
.then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.message == "OK") {
this.setState({ dataGs: result.data.data });
} else {
NotificationManager.error('Failed retreiving data!!', 'Failed');
}
}
getDataSales = async () => {
const { searchDetail, searchDetailField } = this.state
let url = BASE_URL + "sales/search";
let start = 0
if (this.state.currentPage !== 1) {
start = (this.state.currentPage * this.state.rowsPerPage) - this.state.rowsPerPage
}
const obj = {
"paging": { "start": start, "length": this.state.rowsPerPage },
...searchDetail === "All" &&
{
"filter_columns": [
{ "name": "name", "value": this.state.search.toString() },
{ "name": "phone_number", "value": this.state.search.toString() },
{ "name": "email", "value": this.state.search.toString() },
{ "name": "address", "value": this.state.search.toString() },
{ "name": "name", "value": this.state.search.toString(), "table_name": "m_group_sales" },
],
},
...searchDetail !== "All" && searchDetail !== "Group Sales" &&
{
"columns": [
{ "name": searchDetailField, "logic_operator": "ilike", "operator": "and", "value": this.state.search.toString() }
]
},
...searchDetail === "Group Sales" &&
{
"columns": [
{ "name": searchDetailField, "logic_operator": "ilike", "operator": "and", "value": this.state.search.toString(), "table_name": "m_group_sales" }
]
},
"joins": [
{ "name": "group_sales", "column_results": ["name", "description"] }
],
"orders": { "columns": ["name"], "ascending": true }
}
const result = await axios
.post(url, obj)
.then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.message == "OK") {
this.setState({ dataTable: result.data.data, totalPage: result.data.totalRecord });
} else {
NotificationManager.error('Failed retreiving data!!', 'Failed');
}
}
handleOpenDialog = (type) => {
this.setState({ openDialog: true, typeDialog: type })
this.showChildDialog();
}
handleCloseDialog = (type, data, files) => {
if (type === "save") {
this.saveSales(data, files);
} else if (type === "edit") {
this.editSales(data, files);
this.uploadImage(files, data.id);
}
this.setState({ openDialog: false })
}
toggleAddDialog = () => {
this.setState({ openDialog: !this.state.openDialog })
}
onConfirmDelete = async () => {
const { idDelete } = this.state
let url = BASE_URL + `sales/${idDelete}/delete`;
const result = await axios.delete(url)
.then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.message === "OK") {
this.getDataSales()
this.setState({ idDelete: 0, alertDelete: false })
NotificationManager.success('Data group sales berhasil dihapus!!', 'Success!!');
} else {
this.setState({ idDelete: 0, alertDelete: false })
NotificationManager.error('Data group sales galal dihapus!!', 'Failed!!');
}
}
saveSales = async (obj, files) => {
let url = BASE_URL + "sales/add";
let data = JSON.stringify(obj);
const result = await axios.post(url, data)
.then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.message === "OK") {
let ref_id = parseInt(result.data.data.id);
this.uploadImage(files, ref_id);
NotificationManager.success('Data sales berhasil ditambahkan!!', 'Success!!');
} else {
NotificationManager.error(`${result.data.message}`, 'Failed!!');
}
}
editSales = async (data) => {
let url = BASE_URL + `sales/${data.id}/edit`;
const obj = JSON.stringify(data);
const result = await axios.put(url, obj)
.then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.message === "OK") {
this.getDataSales();
NotificationManager.success('Data sales berhasil diedit!!', 'Success!!');
} else {
NotificationManager.error('Data sales galal diedit!!', 'Failed!!');
}
}
uploadImage = async (files, idRef) => {
if (files.length > 0) {
let promises = [];
let response = [];
let url = BASE_URL + `image/m_sales/upload`;
files.map((val, index) => {
let formData = new FormData();
formData.append("ref_id", idRef);
formData.append("files", val[0]);
promises.push(axios.post(url, formData)
.then(res => { response.push(res) }))
})
await Promise.all(promises);
}
this.getDataSales()
}
handleEdit = (data) => {
this.setState({ dataEdit: data });
this.handleOpenDialog('Edit');
}
handleDelete = (id) => {
this.setState({ alertDelete: true, idDelete: id });
}
onShowSizeChange = (current, pageSize) => {
this.setState({ rowsPerPage: pageSize }, () => {
this.getDataSales();
})
}
onPagination = (current, pageSize) => {
this.setState({ currentPage: current, page: (current - 1) * pageSize }, () => {
this.getDataSales();
})
}
handleSearch = e => {
const value = e.target.value
this.setState({ search: value, currentPage: 1 })
};
toggleDropDown = () => {
this.setState(prevState => ({ splitButtonOpen: !prevState.splitButtonOpen }))
}
toggle = (param) => {
if (param === "edit") {
this.setState(prevState => ({ tooltipEdit: !prevState.tooltipEdit }))
} else if (param === "delete") {
this.setState(prevState => ({ tooltipDelete: !prevState.tooltipDelete }))
}
}
render() {
const { search, openDialog, currentPage, rowsPerPage, totalPage, dataTable, splitButtonOpen, searchDetail, tooltipDelete, tooltipEdit } = this.state
let noSeq = 0;
return (
<div>
<NotificationContainer />
<SweetAlert
show={this.state.alertDelete}
warning
showCancel
confirmBtnText="Delete"
confirmBtnBsStyle="danger"
title="Are you sure?"
onConfirm={this.onConfirmDelete}
onCancel={() => this.setState({ alertDelete: false, idDelete: 0 })}
focusCancelBtn
>
Data group sales akan terhapus!!
</SweetAlert>
<DialogForm
openDialog={openDialog}
closeDialog={this.handleCloseDialog}
toggleDialog={() => this.toggleAddDialog}
typeDialog={this.state.typeDialog}
dataEdit={this.state.dataEdit}
showDialog={showDialog => this.showChildDialog = showDialog}
dataGs={this.state.dataGs}
/>
<Card>
<CardHeader style={{ display: "flex", justifyContent: "space-between" }}>
<h4>Sales</h4>
<div>
<Button color="primary" onClick={() => this.handleOpenDialog('Save')}>Add Sales</Button>
<Link style={{ marginLeft: 16 }} to="/sales/setting-sales">
<Icon width={35} height={35} icon={settingOutlined} />
</Link>
</div>
</CardHeader>
<CardBody>
<InputGroup style={{ maxWidth: "200px", marginBottom: "20px" }}>
<Input onChange={this.handleSearch} value={search} type="text" name="search" id="search" placeholder={`Search ${searchDetail}`} />
<InputGroupButtonDropdown addonType="prepend"
isOpen={splitButtonOpen}
toggle={this.toggleDropDown}
>
<DropdownToggle split outline />
<DropdownMenu>
<DropdownItem onClick={
() => this.setState({
searchDetail: "All",
searchDetailField: "name"
})}>All</DropdownItem>
<DropdownItem onClick={
() => this.setState({
searchDetail: "Name",
searchDetailField: "name"
})}>Name</DropdownItem>
<DropdownItem onClick={
() => this.setState({
searchDetail: "Group Sales",
searchDetailField: "name"
})}>Group Sales</DropdownItem>
<DropdownItem onClick={
() => this.setState({
searchDetail: "Phone Number",
searchDetailField: "phone_number"
})}>Phone Number</DropdownItem>
<DropdownItem onClick={
() => this.setState({
searchDetail: "Email",
searchDetailField: "email"
})}>Email</DropdownItem>
<DropdownItem onClick={
() => this.setState({
searchDetail: "Address",
searchDetailField: "address"
})}>Address</DropdownItem>
</DropdownMenu>
</InputGroupButtonDropdown>
</InputGroup>
<Table responsive striped hover>
<thead>
<tr>
<th>Actions</th>
{column.map((i, index) => {
return (
<th key={index} scope="row">{i.name}</th>
)
})}
</tr>
</thead>
<tbody>
{dataTable.map((n) => {
return (
<tr key={n.id}>
<td>
{/* delete */}
<i id="TooltipDelete" className="cil-trash fa-lg" style={{ color: 'red', marginRight: '10px', cursor: "pointer" }} onClick={() => this.handleDelete(n.id)}></i>
<Tooltip placement="right" isOpen={tooltipDelete} target="TooltipDelete" toggle={() => this.toggle("delete")}>
Delete
</Tooltip>
{/* edit */}
<i id="TooltipEdit" className="cil-pencil fa-lg" style={{ color: 'green', cursor: "pointer" }} onClick={() => this.handleEdit(n)}></i>
<Tooltip placement="right" isOpen={tooltipEdit} target="TooltipEdit" toggle={() => this.toggle("edit")}>
Edit
</Tooltip>
</td>
<td>{n.join.group_sales_name}</td>
<td>{n.name}</td>
<td>{n.phone_number}</td>
<td>{n.email}</td>
<td>{n.address}</td>
</tr>
)
})}
</tbody>
</Table>
<Pagination
showSizeChanger
onShowSizeChange={this.onShowSizeChange}
onChange={this.onPagination}
defaultCurrent={currentPage}
pageSize={rowsPerPage}
total={totalPage}
pageSizeOptions={["10", "15", "20", "25", "30", "35", "40"]}
/>
</CardBody>
</Card>
</div>
)
}
}

0
src/views/Master/MasterSubdistrict/MasterSubdistrict.css

50
src/views/Master/MasterSubdistrict/MasterSubdistrict.js

@ -1,50 +0,0 @@
import React, { Component } from 'react'
import DataTable from '../../../components/DataTable'
import { API_LIST_DATA_SUBDISTRICT, API_INSERT_DATA_SUBDISTRICT, API_UPDATE_DATA_SUBDISTRICT, API_DELETE_DATA_SUBDISTRICT } from '../../../const/ApiConst.js'
const columns = [{
dataField: 'id',
alias: "Id",
showInput: false,
type: "number",
state: 0
}, {
dataField: 'subdistrict_name',
alias: "Subdistrict Name",
showInput: true,
type: "text",
state: ""
}, {
dataField: 'last_updated',
alias: "Last Updated",
showInput: false,
type: "text",
state: ""
}];
class MasterSubdistrict extends Component {
constructor(props) {
super(props)
this.state = {}
}
componentDidMount() {}
render() {
return (
<div>
<DataTable
title="Subdistrict"
columns={columns}
urlParamGet={API_LIST_DATA_SUBDISTRICT}
urlParamInsert={API_INSERT_DATA_SUBDISTRICT}
urlParamUpdate={API_UPDATE_DATA_SUBDISTRICT}
urlParamDelete={API_DELETE_DATA_SUBDISTRICT}
/>
</div>
)
}
}
export default MasterSubdistrict;

6
src/views/Master/MasterSubdistrict/package.json

@ -1,6 +0,0 @@
{
"name": "MasterSubdistrict",
"version": "0.0.0",
"private": true,
"main": "./MasterSubdistrict.js"
}

0
src/views/Master/MasterVillage/MasterVillage.css

50
src/views/Master/MasterVillage/MasterVillage.js

@ -1,50 +0,0 @@
import React, { Component } from 'react'
import DataTable from '../../../components/DataTable'
import { API_LIST_DATA_VILLAGE, API_INSERT_DATA_VILLAGE, API_UPDATE_DATA_VILLAGE, API_DELETE_DATA_VILLAGE } from '../../../const/ApiConst.js'
const columns = [{
dataField: 'id',
alias: "Id",
showInput: false,
type: "number",
state: 0
}, {
dataField: 'village_name',
alias: "Village Name",
showInput: true,
type: "text",
state: ""
}, {
dataField: 'last_updated',
alias: "Last Updated",
showInput: false,
type: "text",
state: ""
}];
class MasterVillage extends Component {
constructor(props) {
super(props)
this.state = {}
}
componentDidMount() {}
render() {
return (
<div>
<DataTable
title="VILLAGE"
columns={columns}
urlParamGet={API_LIST_DATA_VILLAGE}
urlParamInsert={API_INSERT_DATA_VILLAGE}
urlParamUpdate={API_UPDATE_DATA_VILLAGE}
urlParamDelete={API_DELETE_DATA_VILLAGE}
/>
</div>
)
}
}
export default MasterVillage;

6
src/views/Master/MasterVillage/package.json

@ -1,6 +0,0 @@
{
"name": "MasterVillage",
"version": "0.0.0",
"private": true,
"main": "./MasterVillage.js"
}

106
src/views/Master/PlanningVsRealisasi/DialogEdit.js

@ -1,106 +0,0 @@
import React, { Component } from 'react'
import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
import { Col, Row, Button, Form, FormGroup, Label, Input } from 'reactstrap';
import Select from 'react-select'
import axios from 'axios';
import moment from 'moment';
import { TimePicker } from 'antd';
import 'antd/dist/antd.css';
export default class DialogForm extends Component {
constructor(props) {
super(props)
this.state = {
id: 0,
lat:"",
lon:"",
status:"",
name:"",
openDialog: false,
isParentClick: false,
disable: false
}
}
async componentDidMount(){
this.props.showDialog(this.showDialog);
}
async componentDidUpdate (){
if(this.state.isParentClick===true){
const { dataEdit } = this.props
console.log("cek", dataEdit);
this.setState({
id:dataEdit.id,
lat:dataEdit.lat,
lon:dataEdit.lon,
status:dataEdit.status_response,
name:dataEdit.employee_name
})
this.setState({isParentClick:false});
}
}
showDialog = () => {
this.setState({ isParentClick : true });
}
handleSave = () => {
const {
lat,
lon,
status,
id
} = this.state
let data = {
lat,
lon,
status_response:status,
id
}
this.props.closeDialog('save', data);
this.setState({ id:0,lat:"",lon:"",status:'active' });
}
handleCancel = () => {
this.props.closeDialog('cancel', 'none')
}
renderForm = () => {
return(
<Form>
<FormGroup>
<Label>Name</Label>
<Input type="text" value={this.state.name} readOnly />
</FormGroup>
<FormGroup>
<Label>Status Approval</Label>
<Input type="select" disabled={this.state.disable} value={this.state.status} onChange={(e)=>this.setState({ status:e.target.value })}>
<option value="active">Active</option>
<option value="non active">Non Active</option>
</Input>
</FormGroup>
</Form>
)
}
render() {
return (
<Modal isOpen={this.props.openDialog} toggle={this.props.toggleDialog}>
<ModalHeader toggle={this.props.closeDialog}>Edit Status Response</ModalHeader>
<ModalBody>
{this.renderForm()}
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={() => this.handleSave()}>Save</Button>{' '}
<Button color="secondary" onClick={() => this.handleCancel()}>Cancel</Button>
</ModalFooter>
</Modal>
)
}
}

85
src/views/Master/PlanningVsRealisasi/DialogForm.js

@ -1,85 +0,0 @@
import React, { Component } from 'react'
import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
import { Col, Row, Button, Form, FormGroup, Label, Input } from 'reactstrap';
import Map from './Map'
import 'antd/dist/antd.css';
const ERROR_LATLON = "Geom cannot be empty"
const ERROR_COMPANY = "Company cannot be empty"
const ERROR_NAME = "name cannot be empty"
const ERROR_RADIUS = "Buffer Radius cannot be empty"
export default class DialogForm extends Component {
constructor(props) {
super(props)
this.state = {
id: 0,
lat:0,
lon:0,
openDialog: false,
isParentClick: false,
}
}
async componentDidMount(){
this.props.showDialog(this.showDialog);
}
async componentDidUpdate (){
if(this.state.isParentClick===true){
const { dataMap } = this.props
this.setState({
lat:dataMap.lat,
lon:dataMap.lon
})
this.setState({isParentClick:false});
}
}
showDialog = () => {
this.setState({ isParentClick : true });
}
handleSave = () => {
}
handleCancel = () => {
this.props.closeDialog('cancel', 'none')
}
getLocation = (param) => {
console.log(`getLocation`, param)
this.setState({
latlonMessage: param != "" ? "" : ERROR_LATLON,
lat: param.lat,
lon: param.lng,
latlon: `lat:${param.lat} lng:${param.lng}`
})
}
renderForm = () => {
return(
<div style={{ width: '100%', minHeight: '100px' }}>
<Map method={'View'} getLocation={this.getLocation} lat={this.state.lat} lng={this.state.lon} />
</div>
)
}
render() {
return (
<Modal isOpen={this.props.openDialog} toggle={this.props.toggleDialog}>
<ModalHeader toggle={this.props.closeDialog}>Map</ModalHeader>
<ModalBody>
{this.renderForm()}
</ModalBody>
<ModalFooter>
{/* <Button color="primary" onClick={() => this.handleSave()}>{this.props.typeDialog}</Button>{' '} */}
<Button color="secondary" onClick={() => this.handleCancel()}>Close</Button>
</ModalFooter>
</Modal>
)
}
}

104
src/views/Master/PlanningVsRealisasi/DialogView.js

@ -1,104 +0,0 @@
import React, { useEffect, useMemo, useState } from 'react'
import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
import { Button, Form, FormGroup, Label, Input, Col, Row } from 'reactstrap';
import { Select, Table } from 'antd'
import { BASE_SIMPRO } from '../../../const/ApiConst';
import { NotificationContainer, NotificationManager } from 'react-notifications';
import 'antd/dist/antd.css';
import axios from 'axios';
import moment from 'moment';
const { Option } = Select
const DialogView = ({ openDialog, closeDialog, toggleDialog, dataPlanning, nameProyekParent }) => {
const token = localStorage.getItem("token")
const HEADER = {
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`
}
}
const [dataPlan, setDataPlan] = useState([]);
useEffect(() => {
setDataPlan(dataPlanning)
}, [dataPlanning]);
const RenderTableLaporanPlan = (tableData) => {
const columns = [
{
title: 'Tanggal',
dataIndex: 'tanggal',
key: 'tanggal',
render: (text, record) => <>{moment(text.tanggal).format("YYYY-MM-DD")}</>,
},
{ title: 'Jumlah Pekerja', dataIndex: 'jumlah_pekerjaan', key: 'jumlah_pekerjaan' },
{ title: 'Status', dataIndex: 'status', key: 'status' },
{ title: 'deskripsi', dataIndex: 'deskripsi', key: 'deskripsi' },
];
return (
<Table
size="small"
columns={columns}
dataSource={tableData}
/>
)
}
const RenderTablePlan = useMemo(() => {
let idx = 0
const columns = [
{
title: 'No',
dataIndex: 'no',
key: 'id',
render: (text, record) => <>{idx+1}</>,
},
{
title: 'Waspang',
dataIndex: 'created_by',
key: 'created_by',
render: (text, record) => <>{record.created_by}</>,
},
{ title: 'Jumlah Pekerjaan', dataIndex: 'jumlah_pekerjaan', key: 'jumlah_pekerjaan' },
{
title: 'Deskripsi',
dataIndex: 'deskripsi',
key: 'deskripsi',
render: (text, record) => <>{record.deskripsi}</>,
},
];
return (
<Table
size="small"
columns={columns}
expandable={{
expandedRowRender: record => RenderTableLaporanPlan(record.realisasi),
rowExpandable: record => record.realisasi,
}}
dataSource={dataPlan}
/>
)
}, [dataPlan])
return (
<Modal size="xl" isOpen={openDialog} toggle={toggleDialog}>
<ModalHeader className="capitalize" toggle={closeDialog}>View Realisasi</ModalHeader>
<ModalBody>
{RenderTablePlan}
</ModalBody>
<ModalFooter>
{/* <Button color="primary" onClick={() => handleSave()}>{typeDialog}</Button>{' '} */}
<Button className="capitalize" color="secondary" onClick={closeDialog}>Close</Button>
</ModalFooter>
</Modal>
)
}
export default DialogView;

83
src/views/Master/PlanningVsRealisasi/Map.js

@ -1,83 +0,0 @@
import React, { useState, useRef, useMemo, useCallback, useEffect } from 'react'
import { MapContainer, TileLayer, Marker, Popup, Polygon } from 'react-leaflet'
const center = {
lat: -6.200000,
lng: 106.816666
}
const DraggableMarker = (props) => {
const { method } = props
let lat = props.lat
let lng = props.lng
const currentPos = [lat, lng]
console.log(`currentPos`, currentPos)
const [draggable, setDraggable] = useState(true)
const [position, setPosition] = useState(center)
const markerRef = useRef(null)
const eventHandlers = useMemo(
() => ({
dragend() {
const marker = markerRef.current
if (marker != null) {
setPosition(marker.getLatLng())
props.getLocation(marker.getLatLng())
}
},
}),
[],
)
return (
<>
{method === "View" && (
<Marker
eventHandlers={eventHandlers}
position={currentPos}
ref={markerRef}>
</Marker>
)}
{method === "Edit" && (
<Marker
draggable={draggable}
eventHandlers={eventHandlers}
position={currentPos ? currentPos : position}
ref={markerRef}>
</Marker>
)}
{method === "Save" && (
<Marker
draggable={draggable}
eventHandlers={eventHandlers}
position={position}
ref={markerRef}>
</Marker>
)}
</>
)
}
const purpleOptions = { color: 'purple' }
const RenderMap = (props) => {
let lat = props.lat
let lng = props.lng
const currentPos = (lat !== "" && lng !== "") ? [lat, lng] : center
return (
<MapContainer center={currentPos} zoom={13} scrollWheelZoom={false} style={{ height: '70vh' }}>
{/* <Polygon pathOptions={purpleOptions} positions={polygon} /> */}
<TileLayer
attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<DraggableMarker {...props} />
</MapContainer>
)
}
export default RenderMap;

608
src/views/Master/PlanningVsRealisasi/index.js

@ -1,608 +0,0 @@
import React, { Component } from 'react';
import { Card, CardBody, CardHeader, Col, Row, Table, Input, InputGroup } from 'reactstrap';
import { Button } from 'reactstrap';
import axios from 'axios';
import moment from 'moment';
import SweetAlert from 'react-bootstrap-sweetalert';
import DialogForm from './DialogForm';
import DialogEdit from './DialogEdit';
import { NotificationContainer, NotificationManager } from 'react-notifications';
import { Pagination, Tooltip } from 'antd';
import { DatePicker } from 'antd';
import * as XLSX from 'xlsx';
import { PLANNING_REALISASI_SEARCH, PLANNING_SEARCH } from '../../../const/ApiConst.js';
import DialogView from './DialogView';
const { RangePicker } = DatePicker;
const token = window.localStorage.getItem('token');
const config = {
headers:
{
Authorization : `Bearer ${token}`,
"Content-type" : `application/json`
}
};
const proyek_id = localStorage.getItem('proyek_id');
const role_id = localStorage.getItem('role_id');
const column = [
{ name: "No" },
{ name: "Proyek" },
{ name: "Pekerjaan" },
{ name: "Target" },
{ name: "Actual" },
{ name: "Team Leader" },
{ name: "Waspang" },
{ name: "Tanggal" },
{ name: "Lihat" },
]
const LENGTH_DATA = 10
export default class index extends Component {
constructor(props) {
super(props)
this.state = {
dataTable: [],
dataExport: [],
openDialog: false,
openDialogEdit:false,
typeDialog: 'Save',
dataEdit: null,
alertDelete: false,
idDelete: 0,
dataGs: [],
dataIdHo: [],
search: "",
page: 0,
rowsPerPage: LENGTH_DATA,
currentPage: 1,
totalPage: 0,
tooltipMap: false,
tooltipDelete: false,
typeClock: "All",
startDate:moment(moment().format("YYYY-M-D")),
endDate:moment(moment().format("YYYY-M-D")),
currentDay: 'today',
dataMap:"",
tooltipExport:false,
openDialogPlan: false,
dataRealisasi: []
}
}
async componentDidMount() {
this.getDataReportPlanning();
}
async componentDidUpdate(prevProps, prevState) {
const { search,startDate,dataExport } = this.state
if (search !== prevState.search) this.getDataReportPlanning()
if (startDate !== prevState.startDate) this.getDataReportPlanning()
if (dataExport !== prevState.dataExport){
if(dataExport.length > 0){
this.exportExcel()
}
}
}
handleSearch = e => {
const value = e.target.value
this.setState({ search: value, currentPage: 1 })
};
getDataReportPlanning = async () => {
let start = 0;
if (this.state.currentPage !== 1 && this.state.currentPage > 1) {
start = (this.state.currentPage * this.state.rowsPerPage) - this.state.rowsPerPage
}
let dateStart = moment(this.state.startDate).format("YYYY-MM-DD 00:00:00");
let dateEnd = moment(this.state.endDate).format("YYYY-MM-DD 23:59:59");
const formData = {
"columns": [
{
"name": "created_at",
"logic_operator": "range",
"value": dateStart,
"value1": dateEnd,
"operator": "AND"
},
{
"name": "nama",
"logic_operator": "ilike",
"value": this.state.search,
"operator": "AND",
}
],
"joins": [
{
"name": "m_proyek",
"column_join": "proyek_id",
"column_results": [
"nama",
"biaya",
"color_progress",
"jumlah_pekerja",
"pic",
"mulai_proyek",
"akhir_proyek"
]
},
{
"name": "m_subproyek",
"column_join": "subproyek_id",
"column_results": [
"nama",
"biaya",
"color_progress",
"jumlah_pekerja",
"pic",
"mulai_proyek",
"akhir_proyek"
]
},
{
"name": "m_users",
"column_join": "user_id",
"column_results": [
"name",
"username",
"email",
"phone_number",
"gender"
]
}
],
"orders": {
"columns": [
"planning_id"
],
"ascending": true
},
"paging": {
"start": start,
"length": this.state.rowsPerPage
}
}
if(parseInt(role_id)!==1){
formData.columns.push(
{
"name": "id",
"logic_operator": "=",
"value": proyek_id,
"operator": "AND",
"table_name": "m_proyek"
}
)
}
const result = await axios
.post(PLANNING_REALISASI_SEARCH, formData, config)
.then(res => res)
.catch((error) => error.response);
if(result && result.data && result.data.code==200){
console.log("cek res planning", result.data.data)
this.setState({ dataTable: result.data.data, totalPage: result.data.totalRecord });
}else{
NotificationManager.error('Gagal Menerima Data!!', 'Failed');
}
}
handleCloseDialogPlan = () => {
this.setState({openDialogPlan: false})
}
handleOpenDialogPlan = (param) => {
this.setState({openDialogPlan: true})
this.setState({dataRealisasi: param.realisasi})
}
toggleAddDialogPlan = () => {
this.setState({openDialogPlan: !this.stateopenDialogPlan})
}
handleOpenDialog = (type) => {
if(type==="Map"){
this.setState({ openDialog: true })
this.showChildDialog();
}else{
this.setState({ openDialogEdit: true })
this.showDialogEdit();
}
}
handleCloseDialog = () => {
this.setState({ openDialog: false })
}
handleCloseDialogEdit = (type, data) => {
if(type==="save"){
this.updateStatusResponse(data);
}
this.setState({ openDialogEdit: false })
}
toggleMapDialog = () => {
this.setState({ openDialog: !this.state.openDialog })
}
toggleEditDialog = () => {
this.setState({ openDialogEdit:!this.state.openDialogEdit });
}
handleMap = data => {
this.setState({ dataMap: data });
this.handleOpenDialog('Map');
}
handleEdit = data => {
this.setState({ dataEdit:data });
this.handleOpenDialog('Edit');
}
handleDelete = (id) => {
this.setState({ alertDelete: true, idDelete: id });
}
onShowSizeChange = (current, pageSize) => {
this.setState({ rowsPerPage: pageSize }, () => {
this.getDataReportPlanning();
})
}
onPagination = (current, pageSize) => {
this.setState({ currentPage: current, page: (current - 1) * pageSize }, () => {
this.getDataReportPlanning();
})
}
toggle = (param) => {
if (param === "map") {
this.setState(prevState => ({ tooltipMap: !prevState.tooltipMap }))
}else if(param==="edit"){
this.setState(prevState => ({ tooltipEdit: !prevState.tooltipEdit }))
} else if (param === "delete") {
this.setState(prevState => ({ tooltipDelete: !prevState.tooltipDelete }))
} else if (param === "export") {
this.setState(prevState => ({ tooltipExport: !prevState.tooltipExport }))
}
}
handleDatePicker = (date, dateString) => {
this.setState({ startDate:date[0],endDate:date[1] },()=>{
this.getDataReportPlanning();
})
}
handleTipe = (e) => {
this.setState({ typeClock:e.target.value }, () => {
this.getDataReportPlanning();
});
}
handleExportExcel = async () => {
let dateStart = moment(this.state.startDate).format("YYYY-MM-DD 00:00:00");
let dateEnd = moment(this.state.endDate).format("YYYY-MM-DD 23:59:59");
const payload = {
"columns": [
{
"name": "created_at",
"logic_operator": "range",
"value": dateStart,
"value1": dateEnd,
"operator": "AND"
},
{
"name": "nama",
"logic_operator": "ilike",
"value": this.state.search,
"operator": "AND",
}
],
"joins": [
{
"name": "m_proyek",
"column_join": "proyek_id",
"column_results": [
"nama",
"biaya",
"color_progress",
"jumlah_pekerja",
"pic",
"mulai_proyek",
"akhir_proyek"
]
},
{
"name": "m_subproyek",
"column_join": "subproyek_id",
"column_results": [
"nama",
"biaya",
"color_progress",
"jumlah_pekerja",
"pic",
"mulai_proyek",
"akhir_proyek"
]
},
{
"name": "m_users",
"column_join": "user_id",
"column_results": [
"name",
"username",
"email",
"phone_number",
"gender"
]
}
],
"orders": {
"columns": [
"planning_id"
],
"ascending": true
},
"paging": {
"start": 0,
"length": -1
}
}
if(parseInt(role_id)!==1){
payload.columns.push(
{
"name": "id",
"logic_operator": "=",
"value": proyek_id,
"operator": "AND",
"table_name": "m_proyek"
}
)
}
const result = await axios
.post(PLANNING_REALISASI_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((n, index) => {
let dataRow = {
"Proyek": n.join ? n.join.m_proyek_nama : "-",
"Pekerjaan": n.nama ? n.nama : "-",
"Target" : n.jumlah_titik ? n.jumlah_titik : "0",
"Actual" : n.realisasi ? this.renderActual(n.realisasi) : "0",
"Team Leader" : n.join.m_subproyek_pic ? `${n.join.m_subproyek_pic}` : "-",
"Waspang" : n.join.m_users_name ? `${n.join.m_users_name}` : "-",
"Tanggal" : n.target_planning ? moment(n.target_planning).format("DD-MM-YYYY") : "-",
}
excelData.push(dataRow)
})
this.setState({dataExport:excelData})
}else{
NotificationManager.error('Gagal Export Data!!', 'Failed');
}
}
exportExcel = () => {
const dataExcel = this.state.dataExport || [];
const fileName = `Data Planning vs realisasi.xlsx`;
const ws = XLSX.utils.json_to_sheet(dataExcel);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, `Data Planning vs realisasi`);
XLSX.writeFile(wb, fileName);
this.setState({dataExport:[] })
}
updateStatusResponse = async (data) => {
let url = ``;
const formData = new FormData();
formData.append("lat", data.lat);
formData.append("lon", data.lon);
formData.append("status_response", data.status_response);
const result = await axios
.post(url, formData)
.then(res => res)
.catch((error) => error.response);
if(result && result.data){
if (result.data.code_status == 200) {
NotificationManager.success('Berhasil update status response!!', 'Success!');
} else {
NotificationManager.error('Gagal update status response!!', 'Failed');
}
}
}
renderActual = (realisasi) => {
let data = realisasi || []
let sumActual = 0
data.map((val, index) => {
sumActual += parseInt(val.jumlah_pekerjaan)
})
return sumActual
}
renderTable = () => {
const dataTable2 = this.state.dataTable || [];
return (
<tbody>
{dataTable2.length!==0 ? dataTable2.map((n, index) => {
return (
<tr key={index}>
<td>{index + 1}</td>
<td>{ n.join ? n.join.m_proyek_nama : "-" }</td>
<td>{ n.nama ? n.nama : "-"}</td>
<td>{ n.jumlah_titik ? n.jumlah_titik : "0" }</td>
<td>{ n.realisasi ? this.renderActual(n.realisasi) : "0" }</td>
<td>{ n.join.m_subproyek_pic ? `${n.join.m_subproyek_pic}` : "-" }</td>
<td>{ n.join.m_users_name ? `${n.join.m_users_name}` : "-" }</td>
<td>{ n.target_planning ? moment(n.target_planning).format("DD-MM-YYYY") : "-" }</td>
<td>
{/* <i id="TooltipDelete" className="cil-trash fa-lg" style={{ color: 'red', marginRight: '10px', cursor: "pointer" }} onClick={() => this.handleDelete(n.id)}></i>
<Tooltip placement="right" isOpen={this.state.tooltipDelete} target="TooltipDelete" toggle={() => this.toggle("delete")}>
Delete
</Tooltip>*/}
{/* <i id="TooltipEdit" className="cil-pencil fa-lg" style={{ color: 'green', cursor: "pointer" }} onClick={() => this.handleEdit(n)}></i>
<Tooltip placement="right" isOpen={this.state.tooltipEdit} target="TooltipEdit" toggle={() => this.toggle("edit")}>
Edit
</Tooltip>
{' '} */}
<Tooltip title="View Realisasi">
<i onClick={() => this.handleOpenDialogPlan(n)} id="tooltipMap" className="fa fa-eye fa-lg" style={{ color: 'black', cursor: "pointer" }}></i>
</Tooltip>
</td>
</tr>
)
}) : <tr>
<td colSpan="9" align="center">No Data Available</td>
</tr>
}
</tbody>
)
}
handleChangeDay = (e) => {
const val = e.target.value;
this.setState({ currentDay:val });
if(val==="today"){
this.setState({
startDate:moment(moment().format("YYYY-M-D")),
endDate:moment(moment().format("YYYY-M-D")),
currentPage: 1
})
}else if(val==="3 day"){
this.setState({
startDate:moment(moment().subtract(3, "days").format("YYYY-M-D")),
endDate:moment(moment().format("YYYY-M-D")),
currentPage: 1
})
}else if(val==="7 day"){
this.setState({
startDate:moment(moment().subtract(7, "days").format("YYYY-M-D")),
endDate:moment(moment().format("YYYY-M-D")),
currentPage: 1
})
}else{
this.setState({
startDate:moment(moment().format("YYYY-M-D")),
endDate:moment(moment().format("YYYY-M-D")),
currentPage: 1
})
}
}
render() {
const { tooltipExport,dataTable, openDialogEdit, openDialog, currentPage, rowsPerPage, totalPage, search, tooltipMap, tooltipDelete } = this.state
return (
<div>
<NotificationContainer />
{/* <SweetAlert
show={this.state.alertDelete}
warning
showCancel
confirmBtnText="Delete"
confirmBtnBsStyle="danger"
title="Are you sure?"
onConfirm={this.onConfirmDelete}
onCancel={() => this.setState({ alertDelete: false, idDelete: 0 })}
focusCancelBtn
>
Data tipe karyawan akan terhapus!!
</SweetAlert> */}
<DialogForm
openDialog={openDialog}
closeDialog={this.handleCloseDialog}
toggleDialog={() => this.toggleMapDialog}
dataMap={this.state.dataMap}
showDialog={showDialog => this.showChildDialog = showDialog}
/>
<DialogEdit
openDialog={openDialogEdit}
closeDialog={this.handleCloseDialogEdit}
toggleDialog={() => this.toggleEditDialog}
dataEdit={this.state.dataEdit}
showDialog={showDialog => this.showDialogEdit = showDialog}
/>
<Card>
<CardHeader style={{ display: "flex", justifyContent: "space-between" }}>
<h4>Planning Vs Realisasi</h4>
<div>
{/* <Button color="primary" onClick={() => this.handleOpenDialog('Save')}>Tambah Broadcast</Button>{' '} */}
<Tooltip title="Export Excel">
<Button id="TooltipExport" color="primary" onClick={()=> this.handleExportExcel()}><i className="fa fa-print"></i></Button>
</Tooltip>
</div>
</CardHeader>
<CardBody>
<div style={{ display: "flex", justifyContent: "space-between", marginBottom:"25px" }}>
<div style={{ width:"100%",display:"inline-flex",alignItems:"center" }}>
<div style={{ width:"50%",marginRight:"10px",maxWidth:"200px" }}>
<Input type="select" onChange={(e) => this.handleChangeDay(e)} defaultValue={this.state.currentDay}>
<option value="today">Hari Ini</option>
<option value="3 day">3 Hari yang lalu</option>
<option value="7 day">7 Hari yang lalu</option>
</Input>
</div>
<div style={{ width:"50%" }}>
<RangePicker size="default" allowClear={false} value={[this.state.startDate, this.state.endDate]} onChange={this.handleDatePicker}/>{' '}
<Button color="primary" onClick={() => this.getDataReportPlanning()}>Cari</Button>
</div>
</div>
<Input onChange={this.handleSearch} value={search} type="text" name="search" id="search" placeholder="Cari Nama Pekerjaan" style={{ maxWidth: "200px", marginBottom: "20px" }} />
</div>
<Table responsive striped hover>
<thead>
<tr>
{/* <th>Actions</th> */}
{column.map((i, index) => {
return (
<th key={index} scope="row">{i.name}</th>
)
})}
</tr>
</thead>
{ this.renderTable() }
</Table>
<Pagination
showSizeChanger
onShowSizeChange={this.onShowSizeChange}
onChange={this.onPagination}
defaultCurrent={currentPage}
pageSize={rowsPerPage}
total={parseInt(totalPage)}
pageSizeOptions={["10", "15", "20", "25", "30", "35", "40"]}
/>
</CardBody>
</Card>
<DialogView
openDialog={this.state.openDialogPlan}
closeDialog={() => this.handleCloseDialogPlan()}
toggleDialog={() => this.toggleAddDialogPlan()}
dataPlanning={this.state.dataRealisasi}
/>
</div>
)
}
}

211
src/views/Master/UserWaspang/DialogForm.js

@ -1,211 +0,0 @@
import React, { useEffect, useState } from 'react'
import { Modal, ModalHeader, ModalBody, ModalFooter,Row,Col } from 'reactstrap';
import { Button, Form, FormGroup, Label, Input } from 'reactstrap';
import { DatePicker,Select } from 'antd';
import moment from 'moment';
import 'antd/dist/antd.css';
const { Option } = Select
const DialogForm = ({openDialog, closeDialog, toggleDialog, typeDialog, dataEdit, dataRole}) => {
const [id, setId] = useState(0)
const [user_id, setUserId] = useState(0)
const [name, setName] = useState('')
const [username, setUsername] = useState('')
const [birth_place, setBirthPlace] = useState('')
const [birth_date, setBirthDate] = useState(moment(moment().format('YYYY-MM-DD')))
const [email, setEmail] = useState('')
const [phone_number, setPhoneNumber] = useState('')
const [address, setAddress] = useState('')
const [gender, setGender] = useState('Laki-laki')
const [password, setPassword] = useState('')
const [role_id,setIdRole] = useState(null)
useEffect(()=> {
if(typeDialog==="Edit"){
if(dataEdit){
setId(dataEdit.id)
setIdRole(3)
setUserId(dataEdit.user_id)
if(dataEdit.join){
setName(dataEdit.join.m_users_name)
setEmail(dataEdit.join.m_users_email)
setBirthDate(dataEdit.join.m_users_birth_date ? moment(moment(dataEdit.join.m_users_birth_date).format("YYYY-MM-DD")) : moment(moment()))
setBirthPlace(dataEdit.join.m_users_birth_place)
setPhoneNumber(dataEdit.join.m_users_phone_number)
setGender(dataEdit.join.m_users_gender || "Laki-laki")
setAddress(dataEdit.join.m_users_address)
setUsername(dataEdit.join.m_users_username)
}
}
}else{
setId(0)
setName('')
setEmail('')
setBirthDate(moment(moment().format('YYYY-MM-DD')))
setBirthPlace('')
setPhoneNumber('')
setGender('Laki-laki')
setAddress('')
setUsername('')
setPassword('')
setIdRole(3)
setUserId(0)
}
},[dataEdit,openDialog])
const handleSave = () => {
let data = '';
if(typeDialog==="Save"){
data = {
name,
username,
phone_number,
email,
birth_date,
birth_place,
gender,
address,
password,
role_id,
user_id
}
closeDialog('save', data);
}else{
data = {
id,
name,
username,
phone_number,
email,
birth_date,
birth_place,
gender,
address,
role_id,
user_id
}
if(password!==''){
data['password'] = password
}
closeDialog('edit', data);
}
setId(0)
setName('')
setEmail('')
setBirthDate(moment(moment().format('YYYY-MM-DD')))
setBirthPlace('')
setPhoneNumber('')
setGender('Laki-laki')
setAddress('')
setUsername('')
setPassword('')
setIdRole(3)
setUserId(0)
}
const handleCancel = () => {
closeDialog('cancel', 'none')
setId(0)
setName('')
setEmail('')
setBirthDate(moment(moment().format('YYYY-MM-DD')))
setBirthPlace('')
setPhoneNumber('')
setGender('Laki-laki')
setAddress('')
setUsername('')
setPassword('')
setIdRole(null)
setUserId(0)
}
const handleDatePicker = (date, dateString) => {
setBirthDate(date)
}
const setupOption = () => {
return(
<>
{dataRole.map((val, index)=> {
return(
<Option key={index} value={val.id}>{val.name}</Option>
)
})}
</>
)
}
const onChangeRole = (val) => {
setIdRole(val)
}
const renderForm = () => {
return(
<Form>
<Row>
<Col>
<FormGroup>
<Label className="capitalize">Nama</Label>
<Input type="text" value={name} onChange={(e)=> setName(e.target.value)} placeholder={`Nama..`}/>
</FormGroup>
<FormGroup>
<Label>Tempat Lahir</Label>
<Input type="text" value={birth_place} onChange={(e)=> setBirthPlace(e.target.value) } placeholder={`Tempat lahir..`} />
</FormGroup>
<FormGroup>
<Label>Tanggal Lahir</Label>
<DatePicker style={{width:"100%"}} value={birth_date} onChange={handleDatePicker} />
</FormGroup>
<FormGroup>
<Label className="capitalize">Jenis Kelamin</Label>
<Input type="select" value={gender} onChange={(e)=> setGender(e.target.value)} placeholder={`Jenis Kelamin..`}>
<option value="Laki-laki">Laki-laki</option>
<option value="Perempuan">Perempuan</option>
</Input>
</FormGroup>
<FormGroup>
<Label className="capitalize">Alamat</Label>
<Input type="textarea" value={address} onChange={(e)=> setAddress(e.target.value)} placeholder={`Alamat..`} />
</FormGroup>
</Col>
<Col>
<FormGroup>
<Label>Username</Label>
<Input type="text" value={username} onChange={(e)=> setUsername(e.target.value)} placeholder="username.." />
</FormGroup>
<FormGroup>
<Label>Email</Label>
<Input type="text" value={email} onChange={(e)=> setEmail(e.target.value)} placeholder="email.." />
</FormGroup>
<FormGroup>
<Label>Nomor Hp</Label>
<Input type="text" value={phone_number} onChange={(e)=> setPhoneNumber(e.target.value)} placeholder={`Nomor Hp..`} />
</FormGroup>
<FormGroup>
<Label>Password</Label>
<Input type="password" value={password} onChange={(e)=> setPassword(e.target.value)} placeholder="password.." />
</FormGroup>
</Col>
</Row>
</Form>
)
}
return (
<Modal size="lg" isOpen={openDialog} toggle={toggleDialog}>
<ModalHeader className="capitalize" toggle={closeDialog}>{typeDialog=="Save" ? `Tambah` : "Edit"} User Waspang</ModalHeader>
<ModalBody>
{renderForm()}
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={() => handleSave()}>{typeDialog}</Button>{' '}
<Button className="capitalize" color="secondary" onClick={() => handleCancel()}>Batal</Button>
</ModalFooter>
</Modal>
)
}
export default DialogForm;

156
src/views/Master/UserWaspang/DialogProyek.js

@ -1,156 +0,0 @@
import React, { useEffect, useState } from 'react'
import { Modal, ModalHeader, ModalBody, ModalFooter, Row, Col } from 'reactstrap';
import { Button, Form, FormGroup, Label, Input } from 'reactstrap';
import { Select, DatePicker } from 'antd';
import moment from 'moment';
import 'antd/dist/antd.css';
const proyekId = localStorage.getItem('proyek_id');
const { Option } = Select;
const DialogProyek = ({ openDialog, closeDialog, toggleDialog, dataWaspangProyek, dataProyek, waspangId }) => {
const [id, setId] = useState(0)
const [proyek_id, setProyekId] = useState(null)
const [user_id, setUserId] = useState(null)
const [userIdAdd, setUserIdAdd] = useState(0)
const [startDate, setStartDate] = useState(moment(moment()))
const [endDate, setEndDate] = useState(moment(moment()))
const [type, setType] = useState("add")
const [disableSelectProyek, setDisableSelectProyek] = useState(false)
const [role_id, setRoleId] = useState(localStorage.getItem('role_id'))
useEffect(() => {
if (waspangId) {
setUserIdAdd(waspangId)
}
}, [waspangId])
useEffect(() => {
let data = dataWaspangProyek || []
console.log("waspang id", waspangId)
console.log("role_id", role_id)
if (data.length > 0) {
let dataObj = data[0]
setType("edit")
setProyekId(dataObj.proyek_id)
if (dataObj.mulai) {
setStartDate(moment(moment(dataObj.mulai)))
} else {
setStartDate(moment(moment()))
}
if (dataObj.mulai) {
setEndDate(moment(moment(dataObj.akhir)))
} else {
setEndDate(moment(moment()))
}
setUserId(dataObj.user_id)
setId(dataObj.id)
} else {
setProyekId(null)
setStartDate(moment(moment()))
setEndDate(moment(moment()))
setType("add")
}
if (parseInt(role_id) === 2) {
setProyekId(parseInt(proyekId))
setDisableSelectProyek(true)
}
}, [dataWaspangProyek, openDialog])
useEffect(() => {
if (parseInt(role_id) === 2) {
setProyekId(parseInt(proyekId))
setDisableSelectProyek(true)
}
}, [role_id])
const handleCancel = () => {
closeDialog('cancel', 'none')
setId(0)
setProyekId(null)
}
const onChangeParent = (value) => {
setProyekId(value)
}
const setupOption = () => {
return (
<>
{dataProyek.map((val, index) => {
return (
<Option key={index} value={val.id}>{val.nama}</Option>
)
})}
</>
)
}
const handleStartDate = (date, string) => {
setStartDate(date)
}
const handleEndDate = (date, string) => {
setEndDate(date)
}
const handleSave = () => {
let data = {
type,
mulai: startDate,
akhir: endDate,
proyek_id,
user_id
}
if (type === "add") {
data['user_id'] = userIdAdd
}
if (type === "edit") {
data['id'] = id
}
closeDialog("save", data)
}
const renderForm = () => {
return (
<Form>
<FormGroup>
<Label className="capitalize">Proyek</Label>
{/* <Input type="text" value={alias} onChange={(e)=> setAlias(e.target.value)} placeholder={`Icon..`} /> */}
<Select showSearch value={proyek_id} onChange={onChangeParent} placeholder="Select Proyek .." style={{ width: '100%' }} disabled={disableSelectProyek}>
{setupOption()}
</Select>
</FormGroup>
<FormGroup>
<Label className="capitalize">Tanggal Mulai</Label>
<DatePicker style={{ width: "100%" }} value={startDate} onChange={handleStartDate} allowClear={false} />
</FormGroup>
<FormGroup>
<Label className="capitalize">Tanggal</Label>
<DatePicker style={{ width: "100%" }} value={endDate} onChange={handleEndDate} allowClear={false} />
</FormGroup>
</Form>
)
}
return (
<Modal isOpen={openDialog} toggle={toggleDialog}>
<ModalHeader className="capitalize" toggle={() => closeDialog("none", "none")}>Save User Proyek</ModalHeader>
<ModalBody>
{renderForm()}
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={() => handleSave()}>Save</Button>{' '}
<Button className="capitalize" color="secondary" onClick={() => handleCancel()}>Batal</Button>
</ModalFooter>
</Modal>
)
}
export default DialogProyek;

686
src/views/Master/UserWaspang/index.js

@ -1,686 +0,0 @@
import React, { useState, useEffect } from 'react';
import { Card, CardBody, CardHeader, Col, Row, Table, Input } from 'reactstrap';
import { Button } from 'reactstrap';
import axios from 'axios';
import * as XLSX from 'xlsx';
import SweetAlert from 'react-bootstrap-sweetalert';
import DialogForm from './DialogForm';
import { NotificationContainer, NotificationManager } from 'react-notifications';
import { Pagination, Tooltip } from 'antd';
import {
USER_ADD,
USER_SEARCH,
USER_EDIT,
USER_DELETE,
ROLE_SEARCH,
USERROLE_ADD,
USERROLE_EDIT,
USERROLE_DELETE,
USERROLE_SEARCH,
USERPROYEK_SEARCH,
PROYEK_SEARCH,
USERPROYEK_EDIT,
USERPROYEK_ADD
} from '../../../const/ApiConst.js';import moment from 'moment';
import DialogProyek from './DialogProyek';
const token = window.localStorage.getItem('token');
const config = {
headers:
{
Authorization : `Bearer ${token}`,
"Content-type" : `application/json`
}
};
const column =
[
{ name: "Nama" },
{ name: "Tempat Lahir" },
{ name: "Tanggal Lahir" },
{ name: "Nomor Telepon" },
{ name: "Email" },
{ name: "Proyek"}
]
const IndexUser = ({params}) => {
const [dataTable, setDatatable] = useState([])
const [search, setSearch] = useState('')
const [currentPage, setCurrentPage] = useState(1)
const [totalPage, setTotalPage] = useState(0)
const [openDialog, setOpenDialog] = useState(false)
const [typeDialog, setTypeDialog] = useState('Save')
const [idDelete, setIdDelete] = useState(0)
const [dataProyek, setDataProyek] = useState([])
const [alertDelete, setAlertDelete] = useState(false)
const [dataEdit, setDataEdit] = useState([])
const [rowsPerPage, setRowsPerPage] = useState(10)
const [clickOpenModal, setClickOpenModal] = useState(false)
const [allDataUserProyek, setAllDataUserProyek] = useState([])
const [dataRole, setDataRole] = useState([])
const [dataExport, setDataExport] = useState([])
const [openDialogProyek, setOpenDialogProyek] = useState(false)
const [dataWaspangProyek, setDataWaspangProyek] = useState([])
const [waspangId, setWaspangId] = useState([])
const pageName = params.name;
useEffect(()=> {
getAllDataRole();
getAllDataProyek();
getAllDataUserProyek();
},[])
useEffect(()=> {
getDataUser();
},[search,rowsPerPage,currentPage])
useEffect(()=> {
const cekData = dataExport || []
if(cekData.length > 0){
exportExcel()
}
},[dataExport])
const handleSearch = e => {
const value = e.target.value
setSearch(value);
setCurrentPage(1)
};
const getAllDataRole = async () => {
const payload = {
"paging": {"start": 0, "length": -1},
"columns": [
{"name": "name", "logic_operator": "ilike", "value": "", "operator": "AND"}
],
"joins": [],
"orders": {"columns": ["id"], "ascending": false}
}
const result = await axios
.post(ROLE_SEARCH, payload, config)
.then(res => res)
.catch((error) => error.response);
if(result && result.data && result.data.code == 200){
setDataRole(result.data.data);
}else{
}
}
const getAllDataProyek = async () => {
const payload = {
"paging": {"start": 0, "length": -1},
"columns": [
{"name": "nama", "logic_operator": "ilike", "value": "", "operator": "AND"}
],
"joins": [],
"orders": {"columns": ["id"], "ascending": false}
}
const result = await axios
.post(PROYEK_SEARCH, payload, config)
.then(res => res)
.catch((error) => error.response);
if(result && result.data && result.data.code == 200){
setDataProyek(result.data.data);
}else{
}
}
const getAllDataUserProyek = async () => {
const formData = {
"paging": {"start": 0, "length": -1},
"columns": [
],
"joins": [
{
"name":"m_proyek",
"column_join":"proyek_id",
"column_results":[
"nama",
]
}
],
"orders": {"columns": ["id"], "ascending": false}
}
const result = await axios.post(USERPROYEK_SEARCH, formData, config)
.then(res => res)
.catch((error) => error.response);
if(result && result.data && result.data.code===200){
setAllDataUserProyek(result.data.data)
}else{
}
}
const getDataUser = async () => {
let start = 0;
if (currentPage !== 1 && currentPage > 1) {
start = (currentPage * rowsPerPage) - rowsPerPage
}
const payload = {
"paging":{
"start":start,
"length":rowsPerPage
},
"filter_columns":[
{
"name":"name",
"value":"",
"table_name":"m_users"
}
],
"columns":[
{
"name":"name",
"logic_operator":"like",
"value":search,
"operator":"AND",
"table_name":"m_users"
},
{
"name":"id",
"logic_operator":"=",
"value":'3',
"operator":"AND",
"table_name":"m_roles"
}
],
"joins":[
{
"name":"m_users",
"column_join":"user_id",
"column_results":[
"username",
"name",
"email",
"gender",
"phone_number",
"address",
"birth_place",
"birth_date"
]
},
{
"name":"m_roles",
"column_join":"role_id",
"column_results":[
"name"
]
}
],
"orders":{
"columns":[
"id"
],
"ascending":false
}
}
const result = await axios
.post(USERROLE_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 handleOpenDialog = async (type) => {
await setTypeDialog(type)
setOpenDialog(true)
}
const handleCloseDialog = (type, data) => {
if (type === "save") {
saveUser(data);
} else if (type === "edit") {
editUser(data);
}
setDataEdit([])
setOpenDialog(false)
}
const toggleAddDialog = () => {
setOpenDialog(!openDialog)
}
const onConfirmDelete = async () => {
let url = USER_DELETE(idDelete);
const result = await axios.delete(url,config)
.then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.code === 200) {
getDataUser()
setIdDelete(0)
setAlertDelete(false)
NotificationManager.success(`Data user berhasil dihapus!`, 'Success!!');
} else {
setIdDelete(0)
setAlertDelete(false)
NotificationManager.error(`Data user gagal dihapus!}`, 'Failed!!');
}
}
const userRoleDelete = async (id) => {
let url = USERROLE_DELETE(id);
const result = await axios.delete(url,config)
.then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.code === 200) {
} else {
}
}
const saveUser = async (data) => {
const formData = data
const result = await axios.post(USER_ADD, formData, config)
.then(res => res)
.catch((error) => error.response);
if(result && result.data && result.data.code===200){
let dataRes = result.data.data
addUserRole(dataRes.id, data.role_id)
} else {
NotificationManager.error(`${result.data.message}`, 'Failed!!');
}
}
const editUser = async (data) => {
let url = USER_EDIT(data.user_id)
const formData = data
const result = await axios.put(url, formData, config)
.then(res => res)
.catch((error) => error.response);
if(result && result.data && result.data.code===200){
editUserRole(data)
} else {
NotificationManager.error(`${result.data.message}`, `Failed!!`);
}
}
const addUserRole = async (user_id, role_id) => {
const formData = {
user_id,
role_id
}
const result = await axios.post(USERROLE_ADD, formData, config)
.then(res => res)
.catch((error) => error.response);
if(result && result.data && result.data.code===200){
getDataUser();
NotificationManager.success(`Data user berhasil ditambahkan`, 'Success!!');
} else {
NotificationManager.error(`${result.data.message}`, `Failed!!`);
}
}
const editUserRole = async (data) => {
let url = USERROLE_EDIT(data.id)
const formData = {
user_id:data.user_id,
role_id:data.role_id
}
const result = await axios.put(url, formData, config)
.then(res => res)
.catch((error) => error.response);
if(result && result.data && result.data.code===200){
getDataUser();
NotificationManager.success(`Data user berhasil di edit`, 'Success!!');
} else {
NotificationManager.error(`${result.data.message}`, `Failed!!`);
}
}
const handleEdit = async (data) => {
await setDataEdit(data)
handleOpenDialog('Edit');
}
const handleDelete = async (id) => {
await setAlertDelete(true)
await setIdDelete(id)
}
const onShowSizeChange = (current, pageSize) => {
setRowsPerPage(pageSize)
}
const onPagination = (current, pageSize) => {
setCurrentPage(current)
}
const handleExportExcel = async () => {
const payload = {
"paging":{
"start":0,
"length":-1
},
"filter_columns":[
{
"name":"name",
"value":"",
"table_name":"m_users"
}
],
"columns":[
{
"name":"name",
"logic_operator":"like",
"value":search,
"operator":"AND",
"table_name":"m_users"
}
],
"joins":[
{
"name":"m_users",
"column_join":"user_id",
"column_results":[
"username",
"name",
"email",
"gender",
"phone_number",
"address",
"birth_place",
"birth_date"
]
},
{
"name":"m_roles",
"column_join":"role_id",
"column_results":[
"name"
]
}
],
"orders":{
"columns":[
"id"
],
"ascending":false
}
}
const result = await axios
.post(USERROLE_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((n, index) => {
let dataRow = {
"Name" :n.join.m_users_name ? n.join.m_users_name : "-",
"Email" :n.join.m_users_email ? n.join.m_users_email : "-",
"Username" :n.join.m_users_username ? n.join.m_users_username : "-",
"Phone Number":n.join.m_users_phone_number ? n.join.m_users_phone_number : "-",
"Address":n.join.m_users_address ? n.join.m_users_address : "-",
"Birth Date":n.join.m_users_birth_date ? moment(n.join.m_users_birth_date).format("YYYY-MM-DD") : "-",
"Birth Place":n.join.m_users_birth_place ? n.join.m_users_birth_place : "-",
"Gender":n.join.m_users_gender ? n.join.m_users_gender : "-"
}
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);
}
const cancelDelete = () => {
setAlertDelete(false)
setIdDelete(0)
}
const renderRoleProyek = (role_name, user_id) => {
const userProyek = allDataUserProyek || []
let index = userProyek.findIndex(x => parseInt(x.user_id) === parseInt(user_id));
if(index>=0){
return allDataUserProyek[index].join.m_proyek_nama
}else{
return role_name;
}
}
const handleWaspangProyek = async (data) => {
await setWaspangId(data.user_id)
getDataWaspangProyek(data.user_id);
}
const getDataWaspangProyek = async (id) => {
const formData = {
"paging": {"start": 0, "length": -1},
"columns": [
{"name": "user_id", "logic_operator": "=", "value": id.toString(), "operator": "AND"}
],
"joins": [],
"orders": {"columns": ["id"], "ascending": false}
}
const result = await axios.post(USERPROYEK_SEARCH, formData, config)
.then(res => res)
.catch((error) => error.response);
if(result && result.data && result.data.code===200){
let dataRes = result.data.data
if(dataRes.length > 0){
await setDataWaspangProyek(result.data.data)
setOpenDialogProyek(true)
}else {
await setDataWaspangProyek([])
setOpenDialogProyek(true)
}
} else {
NotificationManager.error(`${result.data.message}`, `Failed!!`);
}
}
const closeProyekDialog = (type, data) => {
if(type==="save"){
if(data.type==="add"){
saveWaspangProyek(data)
}else{
editWaspangProyek(data)
}
}
setOpenDialogProyek(false)
}
const saveWaspangProyek = async (data) => {
const formData = data
const result = await axios.post(USERPROYEK_ADD, formData, config)
.then(res => res)
.catch((error) => error.response);
if(result && result.data && result.data.code===200){
NotificationManager.success(`Data user proyek berhasil ditambahkan`, 'Success!!');
} else {
NotificationManager.error(`${result.data.message}`, `Failed!!`);
}
}
const editWaspangProyek = async (data) => {
let url = USERPROYEK_EDIT(data.id)
const formData = data
const result = await axios.put(url, formData, config)
.then(res => res)
.catch((error) => error.response);
if(result && result.data && result.data.code===200){
NotificationManager.success(`Data user proyek berhasil diedit`, 'Success!!');
} else {
NotificationManager.error(`${result.data.message}`, `Failed!!`);
}
}
const toggleProyekDialog = () => {
setOpenDialogProyek(!openDialogProyek)
}
return (
<div>
<NotificationContainer />
<SweetAlert
show={alertDelete}
warning
showCancel
confirmBtnText="Delete"
confirmBtnBsStyle="danger"
title={`Apakah kamu yakin?`}
onConfirm={onConfirmDelete}
onCancel={() => cancelDelete()}
focusCancelBtn
>
Data user waspang akan terhapus!!
</SweetAlert>
<DialogForm
openDialog={openDialog}
closeDialog={handleCloseDialog}
toggleDialog={() => toggleAddDialog}
typeDialog={typeDialog}
dataEdit={dataEdit}
clickOpenModal={clickOpenModal}
dataRole={dataRole}
/>
<DialogProyek
openDialog={openDialogProyek}
closeDialog={closeProyekDialog}
dataProyek={dataProyek}
dataWaspangProyek={dataWaspangProyek}
toggleDialog={toggleProyekDialog}
waspangId={waspangId}
/>
<Card>
<CardHeader style={{ display: "flex", justifyContent: "space-between" }}>
<h4>{pageName}</h4>
<Row>
<Col>
<Input onChange={handleSearch} value={search} type="text" name="search" id="search" placeholder={`Cari nama`} />
</Col>
<Col>
<Tooltip title="Tambah User Waspang">
<Button id="TooltipTambah" color="success" onClick={() => handleOpenDialog('Save')}><i className="fa fa-plus"></i></Button>
</Tooltip>
<Tooltip title="Export Excel">
<Button style={{marginLeft:"5px"}} id="TooltipExport" color="primary" onClick={()=> handleExportExcel()}><i className="fa fa-print"></i></Button>
</Tooltip>
</Col>
</Row>
</CardHeader>
<CardBody>
<Table responsive striped hover>
<thead>
<tr>
<th className="capitalize">Aksi</th>
{column.map((i, index) => {
return (
<th key={index} scope="row">{i.name}</th>
)
})}
</tr>
</thead>
<tbody>
{dataTable.length<=0 ?
<tr>
<td colSpan="7" align="center">No Data Available</td>
</tr> : null}
{dataTable.map((n, index) => {
return (
<tr key={index}>
<td>
<Tooltip title="Delete">
<i id="TooltipDelete" className="fa fa-trash" style={{ color: 'red', marginRight: '10px', cursor: "pointer" }} onClick={() => handleDelete(n.user_id)}></i>
</Tooltip>
<Tooltip title="Edit">
<i id="TooltipEdit" className="fa fa-pencil" style={{ color: 'green', cursor: "pointer",marginRight: '10px' }} onClick={() => handleEdit(n)}></i>
</Tooltip>
<Tooltip title={`Proyek`}>
<i onClick={() => handleWaspangProyek(n)} style={{color:"black", cursor: "pointer"}} className="cil-task"></i>
</Tooltip>
</td>
<td>{n.join ? n.join.m_users_name : "-"}</td>
<td>{n.join ? n.join.m_users_birth_place || "-" : "-"}</td>
<td>{n.join.m_users_birth_date ? moment(n.join.m_users_birth_date).format("YYYY-MM-DD") : "-"}</td>
<td>{n.join ? n.join.m_users_phone_number : "-"}</td>
<td>{n.join ? n.join.m_users_email : "-"}</td>
{/* <td>{n.join ? n.join.m_roles_name : "-"}</td> */}
<td>{n.join ? n.role_id===3 ? renderRoleProyek(n.join.m_roles_name, n.user_id) : n.join.m_roles_name : "-"}</td>
</tr>
)
})}
</tbody>
</Table>
<Pagination
showSizeChanger
onShowSizeChange={onShowSizeChange}
onChange={onPagination}
defaultCurrent={currentPage}
pageSize={rowsPerPage}
total={totalPage}
pageSizeOptions={["10", "15", "20", "25", "30", "35", "40"]}
/>
</CardBody>
</Card>
</div>
)
}
export default IndexUser;

17
src/views/Pages/Login/Login.js

@ -1,5 +1,4 @@
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import Slider from "react-slick";
@ -19,24 +18,12 @@ import {
InputGroupAddon,
InputGroupText,
Row,
UncontrolledAlert,
Alert,
Carousel,
CarouselIndicators,
CarouselCaption,
CarouselItem,
CarouselControl
} from 'reactstrap';
import { USER_LOGIN, USER_LOGIN_V2, CALERTUSER_SEARCH, MENU_MANAGEMENT, APP_MODE, ROLE_SEARCH } from '../../../const/ApiConst.js';
import { appConfig, reloadConstants } from '../../../const/MapConst.js';
import { APP_NAME } from '../../../const/AppConst.js'
import moment from "moment"
import { USER_LOGIN_V2, CALERTUSER_SEARCH, MENU_MANAGEMENT, ROLE_SEARCH } from '../../../const/ApiConst.js';
import axios from 'axios';
import { NotificationContainer, NotificationManager } from 'react-notifications';
import logo_login_adw from '../../../assets/img/logo_adyawinsa.jpg'
import logo_login_kit from '../../../assets/img/logo_kit.png'
import logo_login_nawakara from '../../../assets/img/logo_nawakara.png'
import logo_login_si from '../../../assets/img/logo-surveyor-indonesia.png'
import logo_ospro from '../../../assets/img/OSPRO.png'
const antIcon = <LoadingOutlined style={{ fontSize: 24 }} spin />;

1
src/views/SimproV2/CreatedProyek/AsignHrProject.js

@ -120,6 +120,7 @@ const AssignHrProject = ({ openDialog, closeDialog, toggleDialog, idTask, compan
},
"columns": [
{ "name": "created_by", "logic_operator": "ilike", "value": "" },
{ "name": "company_id", "logic_operator": "=", "value": company_id },
],
"joins": [],
"orders": {

25
src/views/SimproV2/CreatedProyek/DialogFormGantt.js

@ -2,11 +2,11 @@ import React, { useEffect, useState } from 'react'
import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
import { Button, Form, FormGroup, Label, Input, Col, Row } from 'reactstrap';
import axios from "../../../const/interceptorApi";
import { VERSION_GANTT_ADD, VERSION_GANTT_EDIT } from '../../../const/ApiConst';
import { VERSION_GANTT_ADD, VERSION_GANTT_EDIT, USER_VERSION_GANTT_ADD } from '../../../const/ApiConst';
import { Select } from 'antd';
import 'antd/dist/antd.css';
const DialogFormGantt = ({ openDialog, closeDialog, toggleDialog, idTask, parentId, dataEdit, typeDialog}) => {
const DialogFormGantt = ({ openDialog, closeDialog, toggleDialog, idTask, parentId, dataEdit, typeDialog, user_id }) => {
const token = localStorage.getItem("token")
const HEADER = {
headers: {
@ -30,8 +30,7 @@ const DialogFormGantt = ({ openDialog, closeDialog, toggleDialog, idTask, parent
}
}
useEffect(() => {
if(typeDialog === "Edit")
{
if (typeDialog === "Edit") {
setId(dataEdit.id);
setName(dataEdit.name_version);
setDesctription(dataEdit.description);
@ -77,6 +76,14 @@ const DialogFormGantt = ({ openDialog, closeDialog, toggleDialog, idTask, parent
.catch((error) => error.response);
if (result && result.status == 200) {
const formData = {
user_id: user_id,
version_gantt_id: result.data.id
}
await axios
.post(USER_VERSION_GANTT_ADD, formData, HEADER)
.then(res => res)
.catch((error) => error.response);
closeDialog('Save')
} else {
closeDialog('failed')
@ -87,7 +94,7 @@ const DialogFormGantt = ({ openDialog, closeDialog, toggleDialog, idTask, parent
const formData = {
name_version: data.name,
description:data.description,
description: data.description,
calculation_type: data.calculationType,
proyek_id: idTask,
hierarchy_ftth_id: parentId
@ -115,11 +122,11 @@ const DialogFormGantt = ({ openDialog, closeDialog, toggleDialog, idTask, parent
<Form>
<FormGroup>
<Label className="capitalize">Nama <span style={{ color: "red" }}>*</span> </Label>
<Input type="text" value={name} onChange={(e) => setName(e.target.value)}/>
<Input type="text" value={name} onChange={(e) => setName(e.target.value)} />
</FormGroup>
<FormGroup>
<Label className="capitalize">Deskripsi </Label>
<Input type="textarea" value={description} onChange={(e) => setDesctription(e.target.value)}/>
<Input type="textarea" value={description} onChange={(e) => setDesctription(e.target.value)} />
</FormGroup>
<FormGroup>
<Label className="capitalize">Tipe Kalkulasi </Label>
@ -157,12 +164,12 @@ const DialogFormGantt = ({ openDialog, closeDialog, toggleDialog, idTask, parent
return (
<>
<Modal isOpen={openDialog} toggle={toggleDialog}>
<ModalHeader className="capitalize" toggle={closeDialog}>{typeDialog == "Edit" ? "Edit" :"Tambah"} Gantt Project</ModalHeader>
<ModalHeader className="capitalize" toggle={closeDialog}>{typeDialog == "Edit" ? "Edit" : "Tambah"} Gantt Project</ModalHeader>
<ModalBody>
{renderForm()}
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={() => handleSave()}>{typeDialog == "Edit" ? "Update" :"Save"}</Button>{' '}
<Button color="primary" onClick={() => handleSave()}>{typeDialog == "Edit" ? "Update" : "Save"}</Button>{' '}
<Button className="capitalize" color="secondary" onClick={() => handleCancel()}>Cancel</Button>
</ModalFooter>
</Modal>

15
src/views/SimproV2/CreatedProyek/DialogGantt.js

@ -1,5 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react'
import { Modal, ModalHeader, ModalBody, ModalFooter, Breadcrumb, BreadcrumbItem} from 'reactstrap';
import { Modal, ModalHeader, ModalBody, ModalFooter, Breadcrumb, BreadcrumbItem } from 'reactstrap';
import { Button } from 'reactstrap';
import { Table, Tooltip, Spin } from 'antd';
import 'antd/dist/antd.css';
@ -19,13 +19,11 @@ const DialogGantt = ({ openDialog, closeDialog, toggleDialog, idTask, proyekName
user_id = user_id;
token = token;
isLogin = isLogin;
console.log('props.location.state success');
} else {
role_id = localStorage.getItem("role_id");
user_id = localStorage.getItem("user_id");
token = localStorage.getItem("token");
isLogin = localStorage.getItem("isLogin");
console.error('Undefined in props.location.state');
}
const HEADER = {
headers: {
@ -171,7 +169,7 @@ const DialogGantt = ({ openDialog, closeDialog, toggleDialog, idTask, proyekName
role_id: role_id,
user_id: user_id,
}
}}>
}}>
<Tooltip title="Gantt">
<Button size={"sm"} color='primary'><i className="fa fa-gears"></i></Button>
</Tooltip></Link>{" "}
@ -233,10 +231,10 @@ const DialogGantt = ({ openDialog, closeDialog, toggleDialog, idTask, proyekName
if (status == "Save") {
getdataGantt()
NotificationManager.success(`Gantt berhasil dibuat!`, 'Success!!');
}else if (status == "Edit") {
} else if (status == "Edit") {
getdataGantt()
NotificationManager.success(`Gantt berhasil dibubah!`, 'Failed!!');
}else if (status == "failed") {
} else if (status == "failed") {
NotificationManager.error(`Gantt gagal dibuat!`, 'Failed!!');
}
setDataEdit([])
@ -269,10 +267,10 @@ const DialogGantt = ({ openDialog, closeDialog, toggleDialog, idTask, proyekName
<BreadcrumbItem><a href="/projects">Project</a></BreadcrumbItem>
<BreadcrumbItem active>{hierarchyName}</BreadcrumbItem>
</Breadcrumb>
:
:
<div>Gantt Project {proyekName} </div>
}
{!hierarchyId && (<> <Button onClick={handleOpenDialogForm} size='sm' color="primary"><i className='fa fa-plus'></i></Button>
{!hierarchyId && (<> <Button onClick={handleOpenDialogForm} size='sm' color="primary"><i className='fa fa-plus'></i></Button>
</>
)}
</ModalHeader>
@ -308,6 +306,7 @@ const DialogGantt = ({ openDialog, closeDialog, toggleDialog, idTask, proyekName
closeDialog={closeDialogForm}
typeDialog={typeDialog}
dataEdit={dataEdit}
user_id={user_id}
/>
<DialogUserGantt

12
src/views/SimproV2/CreatedProyek/index.js

@ -85,13 +85,14 @@ const url = "";
const format = "DD-MM-YYYY";
const CreatedProyek = ({ params, ...props }) => {
let role_id = '', user_id = '', proyek_id = '', isLogin = '', token = '', company_id = 0;
let role_id = '', user_id = '', proyek_id = '', isLogin = '', token = '', company_id = 0, all_project = '';
if (props.location.state && props.location.state.role_id && props.location.state.user_id) {
role_id = props.location.state.role_id;
user_id = props.location.state.user_id;
token = props.location.state.token;
isLogin = props.location.state.isLogin;
company_id = props.location.state.company_id;
all_project = props.location.state.all_project;
} else {
role_id = localStorage.getItem("role_id");
@ -100,6 +101,7 @@ const CreatedProyek = ({ params, ...props }) => {
token = localStorage.getItem("token");
isLogin = localStorage.getItem("isLogin");
company_id = localStorage.getItem('company_id');
all_project = localStorage.getItem('all_project');
}
const history = useHistory();
const HEADER = {
@ -374,7 +376,11 @@ const CreatedProyek = ({ params, ...props }) => {
paging: { start: start, length: rowsPerPage },
};
if (parseInt(role_id) !== 70) {
if (all_project) {
payload["columns"] = [
{ name: "company_id", logic_operator: "like", value: company_id, operator: "AND" }
];
} else {
payload["columns"] = [
{ name: "created_by_id", logic_operator: "IN", value: hierarchy, operator: "AND" }
];
@ -506,6 +512,7 @@ const CreatedProyek = ({ params, ...props }) => {
};
const handleOpenDialogGantt = (data) => {
setDataViewStartDate(data.mulai_proyek)
setidTask(data.id);
setProyekName(data.nama);
setOpenDialogGantt(true);
@ -1975,6 +1982,7 @@ const CreatedProyek = ({ params, ...props }) => {
token={token}
isLogin={isLogin}
proyekName={proyekName}
dataViewStartDate={dataViewStartDate}
/>
),
[openDialogGantt]

2
src/views/SimproV2/ResourceWorker/DialogForm.js

@ -327,7 +327,7 @@ const DialogForm = ({ openDialog, closeDialog, toggleDialog, typeDialog, dataEdi
<Col md={6}>
<FormGroup>
<Label className="capitalize">{t('address')}</Label>
<Input type="textarea" value={address} onChange={(e) => setAddress(e.target.value)} placeholder={t('inputAddress')} />
<Input type="textarea" value={address} onChange={(e) => setAddress(e.target.value)} placeholder={t('inputaddress')} />
</FormGroup>
</Col>

Loading…
Cancel
Save