Fakultas Ilmu Komputer UI

Commit f213e351 authored by Yasmin Adelia Puti Chaidir's avatar Yasmin Adelia Puti Chaidir
Browse files

Merge branch 'staging' of...

Merge branch 'staging' of https://gitlab.cs.ui.ac.id/ppl-fasilkom-ui/2021/DD/justika-pengembangan-platform-untuk-umkm/justika-umkm-legal-frontend into PBI-1-halaman-utama
parents 91ecf774 2f82472d
......@@ -11,9 +11,6 @@ setup:
stage: setup
script:
- npm ci
except:
changes:
- "README.md"
cache:
key: dependency
paths:
......@@ -24,9 +21,6 @@ lint:
script:
- npm install eslint eslint-plugin-jest eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-testing-library
- node_modules/eslint/bin/eslint.js .
except:
changes:
- "README.md"
cache:
key: dependency
policy: pull
......@@ -37,9 +31,6 @@ test:
stage: test-build
script:
- npm run test:coverage
except:
changes:
- "README.md"
artifacts:
expire_in: 1 hour
paths:
......@@ -55,9 +46,6 @@ build:
stage: test-build
script:
- npm run build
except:
changes:
- "README.md"
artifacts:
expire_in: 1 hour
paths:
......@@ -76,9 +64,6 @@ integration:
- npm run cypress:install
- npm run start:gitlab
- npm run cypress:gitlab
except:
changes:
- "README.md"
cache:
key: dependency
policy: pull
......@@ -122,9 +107,6 @@ SonarScanner:
deploy-staging:
stage: deploy
except:
changes:
- "README.md"
script:
- npm install netlify-cli -g --unsafe-perm=true
- netlify deploy --site $NETLIFY_SITE_ID_STAGING --auth $NETLIFY_AUTH_TOKEN --prod
......@@ -135,9 +117,6 @@ deploy-staging:
deploy-master:
stage: deploy
except:
changes:
- "README.md"
script:
- npm install netlify-cli -g --unsafe-perm=true
- netlify deploy --site $NETLIFY_SITE_ID --auth $NETLIFY_AUTH_TOKEN --prod
......
......@@ -9,6 +9,7 @@
## Kontributor
Kelompok: ppl?
- Lia Yuliana - 1806141271
- Nabila Ayu Dewanti - 1806205312
- Nurul Srianda Putri - 1806205602
......@@ -17,4 +18,65 @@ Kelompok: ppl?
## Deskripsi Proyek
Proyek ini ditujukan untuk pengembangan tampilan web pada platform hukum (legal) untuk UMKM
\ No newline at end of file
Proyek ini ditujukan untuk pengembangan tampilan web pada platform hukum (legal)
untuk UMKM
## Prasyarat untuk menjalankan proyek di lokal
Untuk menjalankan proyek di lokal, pastikan Anda memiliki prasyarat sebagai
berikut ini:
- `Node.js`
- `npm` dengan versi >= 12.0.0
## Menjalankan Proyek di Lokal
Untuk menjalankan proyek di lokal, lakukan hal ini:
1. _Clone_ sumber kode
```bash
git clone https://gitlab.cs.ui.ac.id/ppl-fasilkom-ui/2021/DD/justika-pengembangan-platform-untuk-umkm/justika-umkm-legal-frontend.git
```
2. Masuk ke direktori sumber kode
```bash
cd justika-umkm-legal-frontend
```
3. Lakukan instalasi proyek
```bash
npm install
```
4. Jalankan program
```bash
npm start
```
Aplikasi web dapat dibuka dengan port 3000
## Menjalankan functional test di lokal
Untuk menjalankan test beserta coverage di lokal, lakukan hal berikut ini:
```bash
npm run test:coverage
```
## Menjalankan Integration test di lokal
Untuk menjalankan integration test di lokal, lakukan hal berikut ini:
```bash
npm run cypress:open
```
Anda juga perlu menyalakan program, jalankan perintah ini:
```bash
npm start
```
{
"highest_count": 10,
"overall_total": 14,
"next": "http://localhost:8000/api/v1/riwayat/?limit=3&offset=3",
"previous": null,
"results": [
{
"id": 1,
"nama_usaha": "PT. Cimol Sejahtera",
"status_entitas": "PT",
"alamat": "JL. Kencana",
"barang_jasa": "Cimol",
"jumlah_karyawan": "11-50",
"kode_kbli": "01234",
"catatan": "Test Catatan",
"user": 1,
"status": "Waiting for Payment",
"type": "Iumk"
},
{
"id": 2,
"nama_usaha": "CV. Mie Sejahtera",
"status_entitas": "CV",
"alamat": "JL. Mawar",
"barang_jasa": "Mie",
"jumlah_karyawan": "11-50",
"kode_kbli": "56789",
"catatan": "Test Catatan",
"user": 1,
"status": "Waiting for Process",
"type": "Iumk"
},
{
"id": 1,
"nama_usaha": "PT. Cimol Sejahtera",
"status_entitas": "PT",
"alamat": "JL. Kencana",
"barang_jasa": "Cimol",
"jumlah_karyawan": "11-50",
"kode_kbli": "01234",
"catatan": "Test Catatan",
"user": 1,
"status": "Clarification",
"type": "PTModel"
},
{
"id": 2,
"nama_usaha": "CV. Mie Sejahtera",
"status_entitas": "CV",
"alamat": "JL. Mawar",
"barang_jasa": "Mie",
"jumlah_karyawan": "11-50",
"kode_kbli": "56789",
"catatan": "Test Catatan",
"user": 1,
"status": "Done",
"type": "PTModel"
}
]
}
import '../support/commands'
describe('Riwayat Page', () => {
beforeEach(() => {
cy.intercept('GET', '**/api/v1/riwayat/?status=null', {
fixture: 'riwayat.json',
}).as('getAllRiwayat')
cy.login()
cy.visit('/riwayat')
})
it('should have correct response body', () => {
cy.wait('@getAllRiwayat')
.its('response')
.should('have.property', 'body')
.then((body) => {
expect(body).to.have.property('highest_count')
expect(body).to.have.property('overall_total')
expect(body).to.have.property('next')
expect(body).to.have.property('previous')
expect(body).to.have.property('results')
})
})
})
......@@ -4,6 +4,7 @@ import Login from './components/Autentikasi/Login'
import FormPendirianPT from './pages/FormPendirianPT'
import FormIUMK from './pages/formiumk'
import {Router} from '@reach/router'
import Riwayat from './pages/riwayat'
function App() {
return (
......@@ -14,6 +15,7 @@ function App() {
<Login path="/login" />
<FormPendirianPT path="/form-pt" />
<FormIUMK path="/form-iumk" />
<Riwayat path="/riwayat" />
</Router>
</div>
)
......
<svg width="66" height="66" viewBox="0 0 66 66" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="33" cy="33" r="33" fill="#F9F9F9"/>
<line x1="33.5" y1="19" x2="33.5" y2="49" stroke="#2B50CB" stroke-width="4"/>
<line x1="48" y1="34.5" x2="18" y2="34.5" stroke="#2B50CB" stroke-width="4"/>
</svg>
......@@ -32,7 +32,7 @@ const Login = () => {
if (loggedIn) {
navigate('/')
} else {
navigate('/login')
navigate('/login', {replace: true})
}
// eslint-disable-next-line
}, [])
......@@ -112,7 +112,8 @@ const Login = () => {
Email
</label>
<input
className="px-4 py-2.5 border-2 border-grey rounded-lg"
className={`px-4 py-2.5 border-2 border-grey rounded-lg
${errors.email ? `bg-pink-100` : ``}`}
type="text"
id="email"
required
......@@ -140,7 +141,7 @@ const Login = () => {
<div className="flex flex-row">
<div className="pt-4">
<button
className="bg-poporange text-white heading-3 py-2.5 shadow rounded-lg submit w-80 text-center"
className="bg-poporange text-white heading-3 py-2.5 shadow rounded-lg submit w-80 text-center hover:bg-poporange-hover"
data-testid="next-button"
>
Selanjutnya
......@@ -163,7 +164,8 @@ const Login = () => {
</label>
<div className="pr-2 border-2 border-grey flex flex-row bg-white rounded-lg">
<input
className="w-11/12 px-4 py-2.5 flex-row rounded-lg"
className={`w-11/12 px-4 py-2.5 flex-row rounded-lg
${errors.password ? `bg-pink-100` : ``}`}
type={maskPassword ? 'password' : 'text'}
data-testid="password-input"
id="password"
......@@ -210,7 +212,7 @@ const Login = () => {
<div className="flex flex-col">
<div className="pt-4">
<button className="bg-poporange text-white heading-3 py-2.5 shadow rounded-lg submit w-80 text-center">
<button className="bg-poporange text-white heading-3 py-2.5 shadow rounded-lg submit w-80 text-center hover:bg-poporange-hover">
Masuk
</button>
</div>
......@@ -223,7 +225,21 @@ const Login = () => {
</div>
</div>
)}
<Toaster />
<Toaster
toastOptions={{
icon: '',
style: {
background: '#FF3333',
borderRadius: '0',
padding: '21px',
color: 'white',
margin: '0',
width: '100vw',
fontFamily: 'Lato',
fontWeight: '700',
},
}}
/>
</div>
)
}
......
......@@ -30,7 +30,7 @@ test('renders login page if not login', () => {
testRender(<Login />, {store})
expect(navigate).toHaveBeenCalledTimes(1)
expect(navigate).toHaveBeenCalledWith('/login')
expect(navigate).toHaveBeenCalledWith('/login', {replace: true})
expect(screen.getByTestId('daftar-url-link')).toBeInTheDocument()
})
......
......@@ -21,7 +21,7 @@ const Card = ({index, image, title, text, url}) => {
<div>
<p className="medium-text mb-3.5">{text}</p>
<Link to={url} data-testid={`card-url-link-${index}`}>
<button className="text-lg text-white bg-popblue font-Lato py-2 w-full rounded-lg">
<button className="text-lg text-white bg-popblue font-Lato py-2 w-full rounded-lg hover:bg-popblue-hover">
Mulai
</button>
</Link>
......
import React from 'react'
import PropTypes from 'prop-types'
const CardPesanan = ({kode, type, nama, harga, waktu, status, index}) => {
return (
<div
className="flex flex-col justify-between bg-white shadow-lg mt-6 px-4 lg:px-6 py-3 rounded-lg w-72 sm:w-80 lg:w-96"
data-testid={`card-riwayat-${index}`}
>
<div>
<div className="mb-3">
<p className="reguler-text">{kode}</p>
<p className="heading-3">
{type == 'PTModel' ? 'Pendirian' : 'Perizinan IUMK'} {nama}
</p>
</div>
</div>
<div className="items-end">
<div className="flex flex-row justify-between">
<div>
<p className="medium-text">Harga</p>
<p className="medium-text font-bold">{harga}</p>
</div>
<div>
<p className="medium-text">Estimasi Pengerjaan</p>
<p className="medium-text font-bold">
{status == 'Done' ? '-' : `${waktu} hari`}
</p>
</div>
</div>
<div className="mt-8">
<p
className={`small-text font-bold items-end text-center float-right rounded-2xl w-28 py-2
${
status == 'Clarification'
? `bg-yellow-100`
: status == 'Waiting for Payment'
? `bg-blue-200`
: status == 'Working Process'
? `bg-yellow-400`
: `bg-gray-300`
}`}
>
{status}
</p>
</div>
</div>
</div>
)
}
CardPesanan.propTypes = {
kode: PropTypes.number,
type: PropTypes.string,
nama: PropTypes.string,
harga: PropTypes.string,
waktu: PropTypes.string,
status: PropTypes.string,
index: PropTypes.number,
}
export default CardPesanan
import {render, screen} from '@testing-library/react'
import CardPesanan from './CardPesanan'
let data = {
kode: 1,
nama: 'PT ABC',
harga: 'Rp8,500,000',
waktu: '19',
status: 'Waiting for Payment',
}
test('renders CardPesanan Element with PTModel type', () => {
render(
<CardPesanan
kode={data.kode}
type={'PTModel'}
nama={data.nama}
harga={data.harga}
waktu={data.waktu}
status={data.status}
/>,
)
const kodeElement = screen.getByText('1')
const typeElement = screen.getByText(/Pendirian/i)
const namaElement = screen.getByText(/PT ABC/i)
const hargaElement = screen.getByText(/Rp8,500,000/i)
const waktuElement = screen.getByText(/19 hari/i)
const statusElement = screen.getByText(/Waiting for Payment/i)
expect(kodeElement).toBeInTheDocument()
expect(typeElement).toBeInTheDocument()
expect(namaElement).toBeInTheDocument()
expect(hargaElement).toBeInTheDocument()
expect(waktuElement).toBeInTheDocument()
expect(statusElement).toBeInTheDocument()
})
test('renders CardPesanan with Iumk type', () => {
render(
<CardPesanan
kode={data.kode}
type={'Iumk'}
nama={data.nama}
harga={data.harga}
waktu={data.waktu}
status={data.status}
/>,
)
const typeElement = screen.getByText(/Perizinan IUMK/i)
expect(typeElement).toBeInTheDocument()
})
test('renders CardPesanan with Clarification status', () => {
render(
<CardPesanan
kode={data.kode}
type={'Iumk'}
nama={data.nama}
harga={data.harga}
waktu={data.waktu}
status={'Clarification'}
/>,
)
const statusElement = screen.getByText(/Clarification/i)
expect(statusElement).toBeInTheDocument()
})
test('renders CardPesanan with Working Process status', () => {
render(
<CardPesanan
kode={data.kode}
type={'Iumk'}
nama={data.nama}
harga={data.harga}
waktu={data.waktu}
status={'Working Process'}
/>,
)
const statusElement = screen.getByText(/Working Process/i)
expect(statusElement).toBeInTheDocument()
})
test('renders CardPesanan with Done status', () => {
render(
<CardPesanan
kode={data.kode}
type={'Iumk'}
nama={data.nama}
harga={data.harga}
waktu={data.waktu}
status={'Done'}
/>,
)
const statusElement = screen.getByText(/Done/i)
expect(statusElement).toBeInTheDocument()
})
import React, {useState} from 'react'
import AddIcon from '../../assets/add-icon.svg'
import ModalCreatePB from '../Modal/ModalCreatePB'
const CardProyekBaru = () => {
const [show, setShow] = useState(false)
const showModal = () => {
setShow(true)
}
const hideModal = () => {
setShow(false)
}
return (
<div
className="bg-grey flex flex-col justify-between items-center mt-6 px-4 lg:px-6 py-3 rounded-lg w-72 sm:w-80 lg:w-96"
data-testid="cardpb"
>
<ModalCreatePB show={show} handleClose={hideModal} />
<button onClick={showModal} data-testid="cardpb-button">
<img
className="flex flex-row items-end justify-between pt-4"
data-testid="cardpb-add-icon"
src={AddIcon}
></img>
</button>
<p
className="heading-3 text-popblue pt-3 text-center pb-4"
data-testid="cardpb-text"
>
Proyek Baru
</p>
</div>
)
}
export default CardProyekBaru
import {render, screen, fireEvent} from '@testing-library/react'
import CardProyekBaru from './CardProyekBaru'
test('renders Card Proyek Baru Element', () => {
render(<CardProyekBaru />)
expect(screen.getByTestId('cardpb-add-icon')).toBeInTheDocument()
expect(screen.getByTestId('cardpb-text')).toBeInTheDocument()
})
test('show Modal Create PB', async () => {
render(<CardProyekBaru />)
const addButton = screen.getByTestId('cardpb-button')
fireEvent.click(addButton)
const showModal = screen.getByTestId('modalpb')
expect(showModal).toBeVisible()
})
test('close Modal Create PB', async () => {
render(<CardProyekBaru />)
const addButton = screen.getByTestId('cardpb-button')
fireEvent.click(addButton)
const closeButton = screen.getByTestId('modalpb-close')
fireEvent.click(closeButton)
const cardPB = screen.getByTestId('cardpb')
expect(cardPB).toBeVisible()
})
......@@ -11,7 +11,7 @@ const FormIUMK1 = ({
}) => {
return (
<form
className="px-4"
className="px-0 md:px-4"
data-testid="form-iumk-1"
onSubmit={handleSubmit(onSubmit)}
>
......@@ -37,7 +37,8 @@ const FormIUMK1 = ({
Nama atau Calon Nama Usaha<span className="text-popred">*</span>
</label>
<input
className="px-2 py-2.5 w-full border-2 border-gray-200 rounded"
className={`px-2 py-2.5 w-full border-2 border-gray-200 rounded
${errors.nama ? `bg-pink-100` : ``}`}
type="text"
id="nama"
data-testid="form-1-nama-field"
......@@ -146,7 +147,8 @@ const FormIUMK1 = ({
Alamat<span className="text-popred">*</span>
</label>