Explorar el Código

smart public transportation client initial implementation

master
taweel hace 2 años
padre
commit
9e4b8c7a57

.gitignore → client/.gitignore Ver fichero


README.md → client/README.md Ver fichero


babel.config.js → client/babel.config.js Ver fichero


package-lock.json → client/package-lock.json Ver fichero

@@ -1829,6 +1829,14 @@
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==",
"dev": true
},
"async-validator": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/async-validator/-/async-validator-1.8.5.tgz",
"integrity": "sha512-tXBM+1m056MAX0E8TL2iCjg8WvSyXu0Zc8LNtYqrVeyoL3+esHRZ4SieE9fKQyyU09uONjnMEjrNBMqT0mbvmA==",
"requires": {
"babel-runtime": "6.26.0"
}
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -1886,6 +1894,15 @@
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
"dev": true
},
"axios": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz",
"integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=",
"requires": {
"follow-redirects": "1.5.2",
"is-buffer": "1.1.6"
}
},
"babel-code-frame": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
@@ -2107,6 +2124,15 @@
"esutils": "2.0.2"
}
},
"babel-runtime": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
"requires": {
"core-js": "2.5.7",
"regenerator-runtime": "0.11.1"
}
},
"babylon": {
"version": "7.0.0-beta.47",
"resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz",
@@ -2198,6 +2224,11 @@
"integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
"dev": true
},
"batch-processor": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/batch-processor/-/batch-processor-1.0.0.tgz",
"integrity": "sha1-dclcMrdI4IUNEMKxaPa9vpiRrOg="
},
"bcrypt-pbkdf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
@@ -3207,8 +3238,7 @@
"core-js": {
"version": "2.5.7",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
"integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==",
"dev": true
"integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw=="
},
"core-util-is": {
"version": "1.0.2",
@@ -3671,7 +3701,6 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"dev": true,
"requires": {
"ms": "2.0.0"
}
@@ -4018,6 +4047,14 @@
"integrity": "sha512-h4FnvXgyfJaA1egXqCwfpecFu1k6U4sPqwvCeux2yEWbu+Avlsa9i07iB5M+M1M2iyfEUnuQDWYCkPCkfO5cpg==",
"dev": true
},
"element-resize-detector": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.1.14.tgz",
"integrity": "sha1-rwZKCmGKggrVcKlcXuxbd74BKME=",
"requires": {
"batch-processor": "1.0.0"
}
},
"elliptic": {
"version": "6.4.1",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz",
@@ -4999,7 +5036,6 @@
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.2.tgz",
"integrity": "sha512-kssLorP/9acIdpQ2udQVTiCS5LQmdEz9mvdIfDcl1gYX2tPKFADHSyFdvJS040XdFsPzemWtgI3q8mFVCxtX8A==",
"dev": true,
"requires": {
"debug": "3.1.0"
}
@@ -6715,8 +6751,7 @@
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
"dev": true
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
},
"is-builtin-module": {
"version": "1.0.0",
@@ -7017,6 +7052,28 @@
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
"dev": true
},
"iview": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/iview/-/iview-3.0.0.tgz",
"integrity": "sha512-9PnDxVGXDLUyx9KAPX4UJnqa3M2PA6HEGESd5sz4setgGBAAYTgPjho+87vvbLWjVxYnAzwtu1FuONWORP9IGA==",
"requires": {
"async-validator": "1.8.5",
"deepmerge": "2.1.1",
"element-resize-detector": "1.1.14",
"js-calendar": "1.2.3",
"lodash.throttle": "4.1.1",
"popper.js": "1.14.4",
"tinycolor2": "1.4.1",
"v-click-outside-x": "3.0.3"
},
"dependencies": {
"deepmerge": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.1.1.tgz",
"integrity": "sha512-urQxA1smbLZ2cBbXbaYObM1dJ82aJ2H57A1C/Kklfh/ZN1bgH4G/n5KWhdNfOK11W98gqZfyYj7W4frJJRwA2w=="
}
}
},
"javascript-stringify": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-1.6.0.tgz",
@@ -7034,6 +7091,11 @@
"topo": "3.0.0"
}
},
"js-calendar": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/js-calendar/-/js-calendar-1.2.3.tgz",
"integrity": "sha512-dAA1/Zbp4+c5E+ARCVTIuKepXsNLzSYfzvOimiYD4S5eeP9QuplSHLcdhfqFSwyM1o1u6ku6RRRCyaZ0YAjiBw=="
},
"js-message": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.5.tgz",
@@ -7344,6 +7406,11 @@
"integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
"dev": true
},
"lodash.throttle": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
"integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
},
"lodash.transform": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.transform/-/lodash.transform-4.6.0.tgz",
@@ -7727,8 +7794,7 @@
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"multicast-dns": {
"version": "6.2.3",
@@ -8452,6 +8518,11 @@
"integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==",
"dev": true
},
"popper.js": {
"version": "1.14.4",
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.4.tgz",
"integrity": "sha1-juwdj/AqWjoVLdQ0FKFce3n9abY="
},
"portfinder": {
"version": "1.0.16",
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.16.tgz",
@@ -9933,8 +10004,7 @@
"regenerator-runtime": {
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
"dev": true
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
},
"regenerator-transform": {
"version": "0.12.4",
@@ -11239,6 +11309,11 @@
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=",
"dev": true
},
"tinycolor2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz",
"integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g="
},
"tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
@@ -11741,6 +11816,11 @@
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==",
"dev": true
},
"v-click-outside-x": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/v-click-outside-x/-/v-click-outside-x-3.0.3.tgz",
"integrity": "sha512-3nPkT+rOsLyy1qkDRp3nAY0a9gXlhKlCaqs5dGAZa5oUe3h5+VOUmkKh9zyGiakQ2kDZriqOUx3YNaUjJVVsjg=="
},
"validate-npm-package-license": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
@@ -11788,6 +11868,11 @@
"resolved": "https://registry.npmjs.org/vue/-/vue-2.5.17.tgz",
"integrity": "sha512-mFbcWoDIJi0w0Za4emyLiW72Jae0yjANHbCVquMKijcavBGypqlF7zHRgMa5k4sesdv7hv2rB4JPdZfR+TPfhQ=="
},
"vue-axios": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/vue-axios/-/vue-axios-2.1.3.tgz",
"integrity": "sha512-F4njDY6yqETynPh4iA/x3ohHuL6eNp4Jnn30VU//L7mrq3x7PwaHAoKrT++XjbKLjjNOZevTAGNyYXrdYEC90A=="
},
"vue-eslint-parser": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz",
@@ -11821,6 +11906,16 @@
"vue-style-loader": "4.1.1"
}
},
"vue-router": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.0.1.tgz",
"integrity": "sha512-vLLoY452L+JBpALMP5UHum9+7nzR9PeIBCghU9ZtJ1eWm6ieUI8Zb/DI3MYxH32bxkjzYV1LRjNv4qr8d+uX/w=="
},
"vue-skycons": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/vue-skycons/-/vue-skycons-1.0.5.tgz",
"integrity": "sha512-m8URw+qOPKWjtoEn9GPeAzxBojkPMDnsY05Ux8M1d8g1mOfCYMY7JK4lRG4js6gp1/32WILZWUMLqerBbDn6yw=="
},
"vue-style-loader": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.1.tgz",

package.json → client/package.json Ver fichero

@@ -8,7 +8,12 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"vue": "^2.5.17"
"axios": "^0.18.0",
"iview": "^3.0.0",
"vue": "^2.5.17",
"vue-axios": "^2.1.3",
"vue-router": "^3.0.1",
"vue-skycons": "^1.0.5"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.0.0-rc.12",

public/favicon.ico → client/public/favicon.ico Ver fichero


public/index.html → client/public/index.html Ver fichero


src/App.vue → client/src/App.vue Ver fichero

@@ -1,18 +1,13 @@
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
<router-view></router-view>
</div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
name: 'app',
components: {
HelloWorld
}
name: 'app'
}
</script>

@@ -23,6 +18,5 @@ export default {
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

src/assets/logo.png → client/src/assets/logo.png Ver fichero


+ 174
- 0
client/src/components/Schedule.vue Ver fichero

@@ -0,0 +1,174 @@
<template>
<div style="background-color: #EFEFEF; padding: 10px;">
<Card shadow class="main-card" v-for="trip in trips" :key="trip.id">
<div slot="title">
<Row>
<Col span="10" style="text-align: start;">
<div>
<h1 >{{trip.id}}</h1>
<span class="header">{{trip.driverName}}</span>
</div>
</Col>
<Col span="8">
<skycon :condition="trip.weather" :width="35" :height="35"/>
</Col>
<Col span="6">
<Tag :color="colorMap[trip.status]"> {{trip.status}} </Tag>
</Col>
</Row>
</div>
<Row>
<Col span="6">
<Row class="header">
Time
</Row>
<Row>
{{trip.time}}
</Row>
</Col>
<Col span="6">
<Row class="header">
ETA
</Row>
<Row>
{{trip.eta}}
</Row>
</Col>
<Col span="6">
<Row class="header">
Load
</Row>
<Row>
{{trip.load}}
</Row>
</Col>
<Col span="6">
<Row class="header">
Traffic
</Row>
<Row>
{{trip.traffic}}
</Row>
</Col>
</Row>
</Card>
</div>
</template>

<script>
export default {
data () {
return {
source: '',
destination: '',
loading: true,
trips: [],
// {
// id: '#2170984',
// driverName: 'Mahmoud Husni',
// status: 'Departed',
// time: '05:05 PM',
// eta: '45 minutes',
// demand: 4,
// load: 5,
// weather: 'clear-day',
// traffic: 'Heavey traffic'
// },
// {
// id: '#542940',
// driverName: 'Abu Melhim',
// status: 'Boarding',
// time: '05:10 PM',
// eta: '45 minutes',
// demand: 37,
// load: 7,
// weather: 'partly-cloudy-night',
// traffic: 'Heavey traffic'
// },
// {
// id: '#8923984',
// driverName: 'Abu Mohammad',
// status: 'Available',
// time: '05:30 PM',
// eta: '45 minutes',
// demand: 106,
// load: 0,
// weather: 'rain',
// traffic: 'Heavey traffic'
// },
// {
// id: '#2343490',
// driverName: 'Ameer Bamieh',
// status: 'Available',
// time: '06:05 PM',
// eta: '30 minutes',
// demand: 99,
// load: 0,
// weather: 'fog',
// traffic: 'Slight traffic'
// },
// {
// id: '#9734932',
// driverName: 'Abd Al-Hadi',
// status: 'Arriving',
// time: '07:30 PM',
// eta: '66 minutes',
// demand: 87,
// load: 0,
// weather: 'snow',
// traffic: 'Heavey traffic'
// }
// ],
colorMap: {
'Departed': 'default',
'Boarding': 'primary',
'Available': 'success',
'Arriving': 'warning'
}
}
},
methods: {
getSchedule () {
this.$Loading.start()
// this.loading = true
// this.axios.get('http://www.mocky.io/v2/5b6ca8693300007800a36ad5?mocky-delay=1500ms')
this.axios.get('http://demo7048081.mockable.io/trips', {
params: {
source: this.source,
destination: this.destination
}
})
.then((response) => {
this.$Loading.finish()
// console.log(response.data)
this.trips = response.data
// this.loading = false
// setTimeout(this.getSchedule, 5000)
})
.catch(err => {
console.log(err)
this.$Loading.error()
this.$Message.error('Something went wrong')
// this.loading = false
// setTimeout(this.getSchedule, 5000)
})
}
},
mounted () {
this.source = this.$route.query.source
this.destination = this.$route.query.dest
this.getSchedule()
}
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.main-card {
margin-top: 5px;
margin-bottom: 15px;
}
.header {
color: #ABABAB;
}
</style>

+ 73
- 0
client/src/components/Search.vue Ver fichero

@@ -0,0 +1,73 @@
<template>
<div class="main-form">
<!-- <Card shadow style="flex: 1;"> -->
<Form :model="formItem" label-position="top" :label-width="0" style="flex: 1;">
<FormItem>
<AutoComplete
v-model="formItem.source"
size="large"
:data="routes"
class="extra-large"
placeholder="From where are you leaving?"
style="width:300px"></AutoComplete>
</FormItem>
<FormItem>
<AutoComplete
v-model="formItem.destination"
size="large"
class="extra-large"
:data="routes"
placeholder="To where are you going?"
style="width:300px"></AutoComplete>
</FormItem>
</Form>
<!-- </Card> -->
<Button style="height: 64px; font-weight: 700; font-size: 1.8em;" class="footer" type="primary" @click="handleSubmit()">Go</Button>
</div>
</template>

<script>
export default {
data () {
return {
formItem: {
source: '',
destination: ''
},
routes: ['Ramallah', 'Nablus', 'Jenin', 'Bethlahem', 'Hebron', 'Gaza', 'Salfit']
}
},
methods: {
handleSubmit () {
this.$router.push({path: 'schedule', query: { source: this.formItem.source, dest: this.formItem.destination }})
}
}
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>
.extra-large input {
height: 65px !important;
text-align: center;
}
.extra-large input::-webkit-input-placeholder {
color: #898989;
}
</style>
<style scoped>
.main-form {
padding: 10px;
display: flex;
align-items: center;
height: 100vh;
margin-top: -50px;
}
.footer {
position: absolute;
bottom: 0;
width: 90%;
left: 5%;
margin-bottom: 10px;
}
</style>

+ 33
- 0
client/src/main.js Ver fichero

@@ -0,0 +1,33 @@
import Vue from 'vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
import VueRouter from 'vue-router'
import App from './App.vue'
import Routers from './router.js'
import iView from 'iview'
import 'iview/dist/styles/iview.css'
import Schedule from './components/Schedule'
import Search from './components/Search'
import VueSkycons from 'vue-skycons'

Vue.use(VueRouter)
Vue.use(iView)
Vue.use(VueSkycons, { color: 'gray' })
Vue.use(VueAxios, axios)

Vue.config.productionTip = false

const routes = [
{ path: '/', component: Search },
{ path: '/schedule', component: Schedule }
]

const RouterConfig = {
routes: routes
};
const router = new VueRouter(RouterConfig)

new Vue({
router: router,
render: h => h(App)
}).$mount('#app')

+ 9
- 0
client/src/router.js Ver fichero

@@ -0,0 +1,9 @@
import Schedule from './components/Schedule'
import Search from './components/Search'

const routes = [
{ path: '/', component: Search },
{ path: '/schedule', component: Schedule }
]

module.export = routes

+ 0
- 58
src/components/HelloWorld.vue Ver fichero

@@ -1,58 +0,0 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>

<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

+ 0
- 8
src/main.js Ver fichero

@@ -1,8 +0,0 @@
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
render: h => h(App)
}).$mount('#app')

Cargando…
Cancelar
Guardar