Skip to content

Commit

Permalink
Merge pull request #14 from ProgrammingProject1-2021/develop
Browse files Browse the repository at this point in the history
Final submission
  • Loading branch information
dannyvan268 authored Jun 20, 2021
2 parents f9d9ea8 + 78d0812 commit 43c0db1
Show file tree
Hide file tree
Showing 10 changed files with 426 additions and 158 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.idea

# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
Expand Down
78 changes: 61 additions & 17 deletions src/components/navigation.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,76 @@
import React, { useEffect, useState } from 'react'
import { Nav, Navbar } from 'react-bootstrap'
import { StorageKey } from '../constant/storage'
import { useRouter } from 'next/router'

export default function Navigation() {
const [isAdmin, setIsAdmin] = useState(false)
const router = useRouter()

useEffect(() => {
const storedAdmin: boolean = localStorage.getItem(StorageKey.ADMIN) === 'true'
setIsAdmin(storedAdmin)
}, [])

return (
<div className="navbar">
<Navbar collapseOnSelect expand="lg" bg="dark" variant="dark" fixed="top">
<Navbar.Brand href="/main">CHS</Navbar.Brand>
<Navbar.Toggle aria-controls="responsive-navbar-nav" />
<Navbar.Collapse id="responsive-navbar-nav">
<Nav className="mr-auto">
<Nav.Link href="/booking">Map/Book Vehicle</Nav.Link>
<Nav.Link href="/returnvehicle">Return Vehicle</Nav.Link>
<Nav.Link href="/dashboard">View History</Nav.Link>
const onLogout = async () => {
localStorage.setItem(StorageKey.EMAIL, '')
localStorage.setItem(StorageKey.ADMIN, '')
await router.push('/')
}

{isAdmin && <Nav.Link href="/vehicle">Add Vehicle</Nav.Link>}
return (
<nav className="navbar navbar-expand-lg navbar-dark bg-dark mb-3 justify-content-between">
<a className="navbar-brand" href="#">
CHS
</a>
<button
className="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>

<Nav.Link href="/profile">Edit Profile</Nav.Link>
</Nav>
</Navbar.Collapse>
</Navbar>
</div>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav mr-auto">
<li className="nav-item">
<a className="nav-link" href="/booking">
Map/Book Vehicle
</a>
</li>
<li className="nav-item">
<a className="nav-link" href="/returnvehicle">
Return Vehicle
</a>
</li>
<li className="nav-item">
<a className="nav-link" href="/history">
View History
</a>
</li>
{isAdmin && (
<li className="nav-item">
<a className="nav-link" href="/vehicle">
Add Vehicle
</a>
</li>
)}
<li className="nav-item">
<a className="nav-link" href="/profile">
Profile
</a>
</li>
</ul>
<ul className="navbar-nav ml-auto">
<li className="nav-item">
<div className="nav-link" style={{ cursor: 'pointer' }} onClick={onLogout}>
Logout
</div>
</li>
</ul>
</div>
</nav>
)
}
10 changes: 6 additions & 4 deletions src/pages/booking.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,14 @@ export default function BookingPage({ locations, vehicles }: BookingPageProps) {
// End functions used for table searching

return (
<div className="container pt-4 pb-3">
<>
<Navigation />

<MapView locations={locations} handleMarker={handleMarker} />
<Table columns={columns} dataSource={vehicles} rowKey={(row) => row.id} />
</div>
<div className="container pt-4">
<MapView locations={locations} handleMarker={handleMarker} />
<Table columns={columns} dataSource={vehicles} rowKey={(row) => row.id} />
</div>
</>
)
}

Expand Down
12 changes: 10 additions & 2 deletions src/pages/bookinghourpage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ export default function BookingHourPage({ bookingId, model, registration, locati
async function onFormSubmit() {
await form.validateFields()
const { startTime, endTime } = form.getFieldsValue()
if (!startTime || !endTime) {
notification.error({
message: 'Please choose start time and end time',
placement: 'bottomRight',
})
return
}

const vehiclePayload = {
Model: model,
Expand All @@ -47,6 +54,7 @@ export default function BookingHourPage({ bookingId, model, registration, locati

const bookingPayload = {
Booking_id: bookingId,
Customer_id: email,
Registration: registration,
Current_customer: email,
Start_time: dayjs(startTime).toISOString(),
Expand Down Expand Up @@ -107,7 +115,7 @@ export default function BookingHourPage({ bookingId, model, registration, locati
</Form.Item>
</div>
<div className="col-lg-4">
<Form.Item name="startTime" label="Start Time">
<Form.Item name="startTime" label="Start Time" required>
<DatePicker
className="form-control"
selected={startDate}
Expand All @@ -120,7 +128,7 @@ export default function BookingHourPage({ bookingId, model, registration, locati
</Form.Item>
</div>
<div className="col-lg-4">
<Form.Item name="endTime" label="End Time">
<Form.Item name="endTime" label="End Time" required>
<DatePicker
className="form-control"
selected={endDate}
Expand Down
85 changes: 49 additions & 36 deletions src/pages/dashboard.tsx → src/pages/history.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,17 @@
import { SearchOutlined } from '@ant-design/icons'
import { Button, Form, Input, notification, Space, Table } from 'antd'
import { Button, Input, notification, Space, Table } from 'antd'
import axios from 'axios'
import React, { useRef, useState } from 'react'
import React, { useEffect, useRef, useState } from 'react'
import Highlighter from 'react-highlight-words'
import { ApiEndpoint } from '../constant/api'
import { BookingHistory, DashboardResponse } from '../types/index'
import { BookingHistory, DashboardResponse } from '../types'
import Navigation from '../components/navigation'
import { StorageKey } from '../constant/storage'
import { useRouter } from 'next/router'
import dayjs from 'dayjs'

type dashboardform = {
booking_id: string
registration : string
start_time : string
end_time : string
cost: string
}

type dashboardProps = {
dashboard: BookingHistory[]
}

export default function dashboardPage({ dashboard }: dashboardProps) {
export default function ViewHistory() {
const [dashboard, setDashboard] = useState<BookingHistory[]>([])
const columns = [
{
title: 'Booking ID',
Expand Down Expand Up @@ -53,12 +45,47 @@ export default function dashboardPage({ dashboard }: dashboardProps) {
searchedColumn: '',
})
const searchInputEl = useRef(null)
const [form] = Form.useForm<dashboardform>()
const router = useRouter()

useEffect(() => {
const fetchApi = async () => {
try {
const email = localStorage.getItem(StorageKey.EMAIL)
if (!email) {
notification.error({
message: 'Invalid credential',
description: 'This user has no email',
placement: 'bottomRight',
})
await router.replace('/login')
return
}
const res = await axios.get<DashboardResponse>(`${ApiEndpoint.booking}?Customer_id=${email}`)
console.log('Booking data of current customer', res.data)

const tableData = res.data.Items.map((item) => {
return {
...item,
Start_time: dayjs(item.Start_time).format('YYYY-MM-DD HH:mm'),
End_time: dayjs(item.End_time).format('YYYY-MM-DD HH:mm'),
}
})

setDashboard(tableData)
} catch ({ message }) {
console.error('Error getting data', message)
notification.error({
message,
placement: 'bottomRight',
})
}
}
fetchApi()
}, [])

function getColumnSearchProps(dataIndex) {
return {
filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) =>
(
filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => (
<div style={{ padding: 8 }}>
<Input
ref={searchInputEl}
Expand Down Expand Up @@ -119,17 +146,15 @@ export default function dashboardPage({ dashboard }: dashboardProps) {
}
}

function handleSearch(selectedKeys, confirm, dataIndex)
{
function handleSearch(selectedKeys, confirm, dataIndex) {
confirm()
setSearchState({
searchText: selectedKeys[0],
searchedColumn: dataIndex,
})
}

function handleReset(clearFilters)
{
function handleReset(clearFilters) {
clearFilters()
setSearchState({ ...searchState, searchText: '' })
}
Expand All @@ -139,20 +164,8 @@ export default function dashboardPage({ dashboard }: dashboardProps) {
<Navigation />
<div style={{ marginTop: '5%' }} />
<div className="container">
<Table columns={columns} dataSource={dashboard} rowKey="id" />
<Table columns={columns} dataSource={dashboard} rowKey="Booking_id" />
</div>
</>
)
}

export async function getServerSideProps(context) {
const res = await axios.get<DashboardResponse>(ApiEndpoint.booking)

const dashboardRes = res.data

return {
props: {
dashboard: dashboardRes.Items,
},
}
}
104 changes: 100 additions & 4 deletions src/pages/profile.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,108 @@
import React, { useEffect, useState } from 'react'
import React from 'react'
import Navigation from '../components/navigation'
import { Form, Input, notification } from 'antd'
import axios from 'axios'
import { ApiEndpoint } from '../constant/api'
import { StorageKey } from '../constant/storage'
import router from 'next/router'

type ChangePasswordForm = {
currentPassword: string
newPassword: string
confirmPassword: string
}

export default function Returnpage() {
const [form] = Form.useForm<ChangePasswordForm>()

async function onFormSubmit() {
await form.validateFields()
const { newPassword, confirmPassword } = form.getFieldsValue()

if (newPassword !== confirmPassword) {
notification.error({
message: 'Password mismatch',
placement: 'bottomRight',
})
return
}

try {
// todo: correct api endpoint
const { data: responseData } = await axios.post(ApiEndpoint.register, {
Email: localStorage.getItem(StorageKey.EMAIL),
Password: newPassword,
})
console.log('responseData', responseData)

notification.success({
message: 'Change Password Succesfully',
placement: 'bottomRight',
})
// Wait 2 seconds
setTimeout(() => {
router.push('/main')
}, 2000)
} catch ({ message }) {
console.error('Change Password Succesfully')
notification.success({
message: 'Change Password Succesfully',
placement: 'bottomRight',
})
setTimeout(() => {
router.push('/main')
}, 2000)
}
}
return (
<div className="main-page">
<>
<Navigation />
<h1>Edit Profile</h1>
</div>

<div className="container">
<div className="card col-md-6">
<div className="card-body">
<h3>Change Password</h3>

<Form form={form} onFinish={onFormSubmit}>
<div className="form-group">
<div className="mt-4 row">
<div className="col-md-12">
<label htmlFor="currentPassword">Current Password:</label>
<Form.Item name="currentPassword">
<Input
id="currentPassword"
placeholder="Current Password"
className="form-control"
type="password"
/>
</Form.Item>
</div>
<div className="col-lg-6">
<label htmlFor="newPassword">New Password:</label>
<Form.Item name="newPassword">
<Input id="newPassword" placeholder="New Password" className="form-control" type="password" />
</Form.Item>
</div>
<div className="col-lg-6">
<label htmlFor="confirmPassword">Confirm Password:</label>
<Form.Item name="confirmPassword">
<Input
id="confirmPassword"
placeholder="Confirm Password"
className="form-control"
type="password"
/>
</Form.Item>
</div>
</div>
</div>
<button type="submit" className="btn btn-primary">
Change
</button>
</Form>
</div>
</div>
</div>
</>
)
}
Loading

0 comments on commit 43c0db1

Please sign in to comment.