This commit is contained in:
Martin Donnelly 2020-04-20 01:35:25 +01:00
commit c41d4b4cec
36 changed files with 6238 additions and 0 deletions

62
.eslintrc.json Normal file
View File

@ -0,0 +1,62 @@
{
"parserOptions": {
"ecmaVersion": 2019,
"sourceType": "module"
},
"env": {
"es6": true,
"browser": true
},
"plugins": [
"svelte3"
],
"overrides": [
{
"files": [
"**/*.svelte"
],
"processor": "svelte3/svelte3"
}
],
"rules": {
"arrow-spacing": "error",
"block-scoped-var": "error",
"block-spacing": "error",
"brace-style": ["error", "stroustrup", {}],
"camelcase": "error",
"comma-dangle": ["error", "never"],
"comma-spacing": ["error", { "before": false, "after": true }],
"comma-style": [1, "last"],
"consistent-this": [1, "_this"],
"curly": [1, "multi"],
"eol-last": 1,
"eqeqeq": 1,
"func-names": 1,
"indent": ["error", 2, { "SwitchCase": 1 }],
"lines-around-comment": ["error", { "beforeBlockComment": true, "allowArrayStart": true }],
"max-len": [1, 240, 2], // 2 spaces per tab, max 80 chars per line
"new-cap": 1,
"newline-before-return": "error",
"no-array-constructor": 1,
"no-inner-declarations": [1, "both"],
"no-mixed-spaces-and-tabs": 1,
"no-multi-spaces": 2,
"no-new-object": 1,
"no-shadow-restricted-names": 1,
"object-curly-spacing": ["error", "always"],
"padded-blocks": ["error", { "blocks": "never", "switches": "always" }],
"prefer-const": "error",
"prefer-template": "error",
"one-var": 0,
"quote-props": ["error", "always"],
"quotes": [1, "single"],
"radix": 1,
"semi": [1, "always"],
"space-before-blocks": [1, "always"],
"space-infix-ops": 1,
"vars-on-top": 1,
"no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 1 }],
"spaced-comment": ["error", "always", { "markers": ["/"] }]
}
}

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/node_modules/
/public/build/
.DS_Store

5
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<includedPredefinedLibrary name="Node.js Core" />
</component>
</project>

6
.idea/misc.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/svelte-traintimes.iml" filepath="$PROJECT_DIR$/.idea/svelte-traintimes.iml" />
</modules>
</component>
</project>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

106
README.md Normal file
View File

@ -0,0 +1,106 @@
*Looking for a shareable component template? Go here --> [sveltejs/component-template](https://github.com/sveltejs/component-template)*
---
# Updates
## 2020-04-17
Added [svelte-preprocess](https://www.npmjs.com/package/svelte-preprocess) preprocessor with support for: PostCSS, SCSS, Less, Stylus, Coffeescript, TypeScript and Pug.
Added [rollup-plugin-node-builtins](https://www.npmjs.com/package/rollup-plugin-node-builtins) Allows the node builtins to be required/imported. Doing so gives the proper shims to support modules that were designed for Browserify, some modules require rollup-plugin-node-globals.
Added [rollup-plugin-node-globals](https://www.npmjs.com/package/rollup-plugin-node-globals) Plugin to insert node globals including so code that works with browserify should work even if it uses process or buffers.
---
# svelte app
This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template.
To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit):
```bash
npx degit sveltejs/template svelte-app
cd svelte-app
```
*Note that you will need to have [Node.js](https://nodejs.org) installed.*
## Get started
Install the dependencies...
```bash
cd svelte-app
npm install
```
...then start [Rollup](https://rollupjs.org):
```bash
npm run dev
```
Navigate to [localhost:5000](http://localhost:5000). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes.
By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`.
## Building and running in production mode
To create an optimised version of the app:
```bash
npm run build
```
You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com).
## Single-page app mode
By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere.
If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json:
```js
"start": "sirv public --single"
```
## Deploying to the web
### With [now](https://zeit.co/now)
Install `now` if you haven't already:
```bash
npm install -g now
```
Then, from within your project folder:
```bash
cd public
now deploy --name my-project
```
As an alternative, use the [Now desktop client](https://zeit.co/download) and simply drag the unzipped project folder to the taskbar icon.
### With [surge](https://surge.sh/)
Install `surge` if you haven't already:
```bash
npm install -g surge
```
Then, from within your project folder:
```bash
npm run build
surge public my-project.surge.sh
```

BIN
icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

4197
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

33
package.json Normal file
View File

@ -0,0 +1,33 @@
{
"name": "svelte-app",
"version": "1.0.0",
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w",
"start": "sirv public"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^11.0.0",
"@rollup/plugin-node-resolve": "^7.0.0",
"autoprefixer": "^9.7.6",
"eslint": "^6.8.0",
"eslint-plugin-svelte3": "^2.7.3",
"node-sass": "^4.13.1",
"rollup": "^1.20.0",
"rollup-plugin-livereload": "^1.0.0",
"rollup-plugin-node-builtins": "^2.1.2",
"rollup-plugin-node-globals": "^1.4.0",
"rollup-plugin-svelte": "^5.0.3",
"rollup-plugin-terser": "^5.1.2",
"svelte": "^3.0.0",
"svelte-preprocess": "^3.7.1"
},
"dependencies": {
"axios": "^0.19.2",
"muicss": "^0.10.1",
"rollup-plugin-replace": "^2.2.0",
"sirv-cli": "^0.4.4",
"spectre.css": "^0.5.8",
"svelte-spa-router": "^2.1.0"
}
}

BIN
public/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

0
public/global.css Normal file
View File

17
public/index.html Normal file
View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'>
<title>Svelte app</title>
<link rel='icon' type='image/png' href='/favicon.png'>
<link rel='stylesheet' href='/build/bundle.css'>
<script defer src='/build/bundle.js'></script>
</head>
<body>
</body>
</html>

91
rollup.config.js Normal file
View File

@ -0,0 +1,91 @@
import svelte from 'rollup-plugin-svelte';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import replace from 'rollup-plugin-replace';
import { terser } from 'rollup-plugin-terser';
import sveltePreprocess from 'svelte-preprocess';
import builtins from 'rollup-plugin-node-builtins';
import globals from 'rollup-plugin-node-globals';
const production = !process.env.ROLLUP_WATCH;
const preprocess = sveltePreprocess({
'scss': {
'includePaths': ['src']
},
'postcss': {
'plugins': [require('autoprefixer')]
}
});
export default {
'input': 'src/main.js',
'output': {
'sourcemap': (!production),
'format': 'iife',
'name': 'app',
'file': 'public/build/bundle.js'
},
'plugins': [
// globals(),
// builtins(),
svelte({
// enable run-time checks when not in production
'dev': !production,
preprocess,
// we'll extract any component CSS out into
// a separate file - better for performance
'css': css => {
css.write('public/build/bundle.css');
}
}),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In
// some cases you'll need additional configuration -
// consult the documentation for details:
// https://github.com/rollup/plugins/tree/master/packages/commonjs
resolve({
'browser': true,
'dedupe': ['svelte']
}),
commonjs(),
replace({
'exclude': 'node_modules/**',
'ENV': JSON.stringify(production ? 'production' : 'development')
}),
// In dev mode, call `npm run start` once
// the bundle has been generated
!production && serve(),
// Watch the `public` directory and refresh the
// browser on changes when not in production
!production && livereload('public'),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser()
],
'watch': {
'clearScreen': false
}
};
function serve() {
let started = false;
return {
writeBundle() {
if (!started) {
started = true;
require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
'stdio': ['ignore', 'inherit', 'inherit'],
'shell': true
});
}
}
};
}

35
src/App.svelte Normal file
View File

@ -0,0 +1,35 @@
<script>
import Router from 'svelte-spa-router';
import {link, push, pop, replace, location, querystring} from 'svelte-spa-router';
import active from 'svelte-spa-router/active'
// Import the list of routes
import routes from './routes'
import Header from "./components/Header.svelte";
function conditionsFailed(event) {
// eslint-disable-next-line no-console
console.error('Caught event conditionsFailed', event.detail)
}
// Handles the "routeLoaded" event dispatched by the router after a route has been successfully loaded
function routeLoaded(event) {
// eslint-disable-next-line no-console
console.info('Caught event routeLoaded', event.detail)
}
// Handles event bubbling up from nested routes
function routeEvent(event) {
// eslint-disable-next-line no-console
console.info('Caught event routeEvent', event.detail)
}
</script>
<style lang="scss" global>
@import "./css/custom.scss";
</style>
<Header/>
<Router {routes} on:conditionsFailed={conditionsFailed} on:routeLoaded={routeLoaded} on:routeEvent={routeEvent} />

View File

@ -0,0 +1,32 @@
<script>
import {link, push, pop, replace, location, querystring} from 'svelte-spa-router';
import active from 'svelte-spa-router/active'
let titleText = 'Traintimes';
let currentMode = 1;
$: titleText = $location;
function goBack() {
console.log('>> Header:goBack');
}
</script>
<style>
</style>
<header id="header">
<div class="mui-appbar mui--appbar-line-height mui--z2">
{#if currentMode === 1}
<div class='mui-col-xs-1 mui-col-md-1 mui--appbar-height'>
<a on:click={goBack} class="">
<i class="fa-3x fa fa-back mui--align-middle" style="color:white;"></i>
</a>
</div>
{/if}
<div class='mui-col-xs-11 mui-col-md-11 mui--appbar-height titleBar'>{titleText}</div>
</div>
</header>

View File

@ -0,0 +1,17 @@
<script>
export let fromStation;
export let destStation;
</script>
<style>
* {
background: #f55a4e;
padding: 3px;
}
</style>
<div>
<span>TimetableList</span>
{fromStation} to {destStation}
</div>

View File

@ -0,0 +1,89 @@
<script>
import {findStation} from '../libs/stations'
import {minuteFloor, LocalStorage} from '../libs/utils'
import {push} from 'svelte-spa-router';
import axios from 'axios';
import {onMount, onDestroy} from 'svelte';
export let destStation;
export let startStation;
let startStationName;
let destStationName;
let url;
let baseUrl = 'http://localhost:8100';
let displayTime;
let trainData = {eta: 'OFF', sta: 'OFF'};
let status;
let timetablePath;
let interval = 0;
$: {
status = (trainData.eta === 'On time') ? 'ontime' : 'delayed';
displayTime = (trainData.eta === 'On time') ? trainData.sta : trainData.eta;
timetablePath = `#/timetable/${startStation}/${destStation}`
}
onMount(async () => {
if( LocalStorage.exists(`${startStation}${destStation}`)) {
const fromLS = JSON.parse(LocalStorage.load(`${startStation}${destStation}`));
trainData = {...trainData, ...fromLS};
}
startStationName = findStation(startStation);
destStationName = findStation(destStation);
url = `${baseUrl}/getnexttraintimes?from=${startStation}&to=${destStation}`;
updateTrain();
});
onDestroy(async () => {
clearInterval(interval);
LocalStorage.save(`${startStation}${destStation}`, JSON.stringify(trainData));
});
function onClick() {
console.log('Onclick', timetablePath);
push(timetablePath);
}
async function updateTrain() {
console.log(`Update: ${startStation} / ${destStation}`)
const now = new Date()
const hours = now.getHours()
const limit = (hours < 6) ? 3600000 : 95000
const mod = limit - (now.getTime() % limit)
await getTrain()
clearTimeout(interval)
interval = 0
interval = setTimeout(updateTrain, mod + 10)
}
async function getTrain() {
const minuteHash = minuteFloor()
const workingUrl = url.concat(`&mh=${minuteHash}`)
axios.get(workingUrl)
.then((d) => {
trainData = {...d.data}
})
}
</script>
<style>
.entry {
height: 36px;
margin: 6px 0;
vertical-align: middle;
}
</style>
<div class="mui-row card">
<div class='mui-col-xs-7 mui-col-md-7 entry'>
<div>{startStationName}</div>
<div>{destStationName}</div>
</div>
<div class='mui-col-xs-5 mui-col-md-5 mui--text-right'>
<span class="mui-btn mui-btn--flat time {status}" on:click={onClick}>{displayTime}</span>
</div>
</div>

View File

@ -0,0 +1,12 @@
<script>
</script>
<style>
* {
background: #f55a4e;
padding: 3px;
}
</style>
<span>TrainService</span>

88
src/css/common.css Normal file
View File

@ -0,0 +1,88 @@
body {
background-color: #eee;
}
.card {
position: relative;
background-color: #fff;
min-height:48px;
margin: 8px;
border-bottom-color: #666666;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
}
.mui--text-display4, .mui--text-display3 {
font-family: "Roboto Slab", "Helvetica Neue", Helvetica, Arial;
}
.temp0, .temp1, .temp2, .temp3, .temp4, .temp5 {
color: rgb(80,181,221)
}
.temp6 {
color: rgb(78,178,206)
}
.temp7 {
color: rgb(76, 176, 190)
}
.temp8 {
color: rgb(73, 173, 175)
}
.temp9 {
color: rgb(72, 171, 159)
}
.temp10 {
color: rgb(70, 168, 142)
}
.temp11 {
color: rgb(68, 166, 125)
}
.temp12 {
color: rgb(66, 164, 108)
}
.temp13 {
color: rgb(102, 173, 94)
}
.temp14 {
color: rgb(135, 190, 64)
}
.temp15 {
color: rgb(179, 204, 26)
}
.temp16 {
color: rgb(214, 213, 28)
}
.temp17 {
color: rgb(249, 202, 3)
}
.temp18 {
color: rgb(246, 181, 3)
}
.temp19 {
color: rgb(244, 150, 26)
}
.temp20 {
color: rgb(236, 110, 5)
}
.day {
font-family: "Roboto Slab", "Helvetica Neue", Helvetica, Arial, sans-serif;
text-transform: uppercase;
}
.summary::first-letter {
text-transform: capitalize
}

336
src/css/custom.scss Normal file
View File

@ -0,0 +1,336 @@
// import MUI colors
@import "./node_modules/muicss/lib/sass/mui/colors";
// customize MUI variables
$mui-primary-color: mui-color("blue-grey", "500");
$mui-primary-color-dark: mui-color("blue-grey", "700");
$mui-primary-color-light: mui-color("blue-grey", "100");
$mui-accent-color: mui-color("deep-purple", "900");
$mui-accent-color-dark: mui-color("indigo", "A100");
$mui-accent-color-light: mui-color("indigo", "A400");
$mui-base-font-family: "Roboto", "Helvetica Neue", Helvetica, Arial, Verdana,
"Trebuchet MS";
// import MUI SASS
@import "./node_modules/muicss/lib/sass/mui";
@import "./src/css/viewport";
@import "./src/css/horscroll";
@import "./src/css/spinner";
////
body {
background-color: mui-color("grey", "100");
}
#header {
position: fixed;
top: 0;
right: 0;
left: 0;
z-index: 2;
transition: left 0.2s;
}
ul {
margin: 0;
padding: 0;
}
li {
display: inline;
margin: 0;
padding: 0 4px 0 0;
}
.dates {
padding: 2px;
border: solid 1px #80007e;
background-color: #ffffff;
}
#btc,
#fx,
#trend {
font-size: 85%;
}
.up,
.ontime,
.trendUp {
color: mui-color("green") !important;
}
.down,
.delayed,
.trendDown {
color: $mui-text-danger !important;
}
.nochange {
color: #000000;
}
.password {
border: 1px solid mui-color("grey", "400");
background-color: mui-color("grey", "200");
font-family: monospace;
white-space: pre;
}
.trendUp:before {
content: "";
}
.trendDown:before {
content: "";
}
.card {
position: relative;
background-color: #fff;
min-height: 48px;
margin: 8px;
border-bottom-color: #666666;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2),
0 1px 5px 0 rgba(0, 0, 0, 0.12);
}
.entry {
height: 36px;
margin: 6px 0;
vertical-align: middle;
}
.time {
font-family: "Roboto";
}
.titleBar {
font-family: "Gotham Light";
font-size: 125%;
}
#trains,
#trainResults {
overflow-y: auto;
transition: all 0.5s;
-webkit-transition: all 0.5s;
}
.tableBody {
transition: all 0.5s;
-webkit-transition: all 0.5s;
}
.unsliced {
height: 455px;
}
.sliced {
height: 300px;
}
/* The snackbar - position it at the bottom and in the middle of the screen */
#snackbar {
visibility: hidden; /* Hidden by default. Visible on click */
min-width: 250px; /* Set a default minimum width */
margin-left: -125px; /* Divide value of min-width by 2 */
background-color: #333; /* Black background color */
color: #fff; /* White text color */
text-align: center; /* Centered text */
border-radius: 2px; /* Rounded borders */
padding: 16px; /* Padding */
position: fixed; /* Sit on top of the screen */
z-index: 1; /* Add a z-index if needed */
left: 50%; /* Center the snackbar */
bottom: 30px; /* 30px from the bottom */
}
/* Show the snackbar when clicking on a button (class added with JavaScript) */
#snackbar.show {
visibility: visible; /* Show the snackbar */
/* Add animation: Take 0.5 seconds to fade in and out the snackbar.
However, delay the fade out process for 2.5 seconds */
/* -webkit-animation: fadein 0.5s, fadeout 0.5s 2.5s;
animation: fadein 0.5s, fadeout 0.5s 2.5s;*/
-webkit-animation: fadein 0.5s;
animation: fadein 0.5s;
}
/* Animations to fade the snackbar in and out */
@-webkit-keyframes fadein {
from {
bottom: 0;
opacity: 0;
}
to {
bottom: 30px;
opacity: 1;
}
}
@keyframes fadein {
from {
bottom: 0;
opacity: 0;
}
to {
bottom: 30px;
opacity: 1;
}
}
@-webkit-keyframes fadeout {
from {
bottom: 30px;
opacity: 1;
}
to {
bottom: 0;
opacity: 0;
}
}
@keyframes fadeout {
from {
bottom: 30px;
opacity: 1;
}
to {
bottom: 0;
opacity: 0;
}
}
.stop-scrolling {
height: 100%;
overflow: hidden;
}
.fullscreen {
position: absolute;
z-index: 5000;
top: 0;
left: 0;
height: 100vh;
width: 100vw;
background-color: mui-color("grey", "300");
background-repeat: no-repeat;
background-position: center top;
}
.fillpanel {
width: 100%;
height: 100%;
background-color: mui-color("amber", "50");
}
.fullscreen .header {
/*position: fixed;
top: 0;
right: 0;
left: 0;
z-index: +1;
transition: left 0.2s;*/
position: sticky;
}
.box {
display: flex;
flex-flow: column;
height: 100%;
// overflow:auto;
}
.box .headerSpacer {
flex: 0 1 66px;
}
.box .content {
flex: 1 1 auto;
background-color: mui-color("white");
overflow: auto;
margin-bottom: 15px;
}
.newsarticle img {
max-height: 100%;
max-width: 100%;
}
.tiny {
font-size: 1rem;
}
.small {
font-size: 2rem;
}
.medium {
font-size: 4rem;
}
.large {
font-size: 6rem;
}
.cardLink {
color: mui-color("blue", "500");
margin-top: 10px;
}
.endbumper {
height: 66px;
}
.seemore {
font-size: 14px;
font-weight: 500;
}
#connectionStatus {
margin-top: 15px;
margin-bottom: 15px;
}
.trafficHeavy {
color: #fa4a50;
}
.trafficLight {
color: #fdbd15;
}
.trafficMedium {
color: #fba010;
}
#map {
height: 180px;
}
#bymeImages {
margin-bottom: 3px;
}
.bbm-wrapper {
z-index: 2000 !important;
}
.cancelledRow {
background: repeating-linear-gradient(
-55deg,
#ff000010,
#ff000010 10px,
#fff 10px,
#fff 20px
);
}
.nrccAlert a {
color:#212121;
}

52
src/css/horscroll.scss Normal file
View File

@ -0,0 +1,52 @@
.scrolling-wrapper-flexbox {
display: flex;
flex-wrap: nowrap;
overflow-x: auto;
.scrollCard, .scrollCardHalf, .imageCard, .hourlyCard {
flex: 0 0 auto;
margin-right: 11px;
}
}
.scrollCard, .scrollCardHalf, .hourlyCard {
width: 250px;
height: 175px;
overflow-y: hidden;
border-radius: 3px;
background-color: #f5f5f5;
padding: 5px;
box-shadow: 0 2px 2px 0 rgba(0,0,0,0.05), 0 2px 1px -2px rgba(0,0,0,0.05), 0 1px 5px 0 rgba(0,0,0,0.05)
}
.scrollCardHalf {
height: 85px;
}
.hourlyCard {
width: 42px;
height:70px;
background: transparent;
}
.imageCard {
// width: 250px;
height: 175px;
overflow-y: hidden;
}
.imageCard img {
max-height:100%;
max-width:100%;
}
.scrolling-wrapper, .scrolling-wrapper-flexbox {
height: 75px;
width: 100%;
-webkit-overflow-scrolling: touch;
&::-webkit-scrollbar {
display: none;
}
}

181
src/css/skeleton-min.css vendored Normal file
View File

@ -0,0 +1,181 @@
.container{position:relative;width:100%;max-width:960px;margin:0 auto;padding:0 20px;box-sizing:border-box;}
.column,
.columns{width:100%;float:left;box-sizing:border-box;}
@media (min-width:400px){.container{width:85%;padding:0;}
}
@media (min-width:550px){.container{width:80%;}
.column,
.columns{margin-left:4%;}
.column:first-child,
.columns:first-child{margin-left:0;}
.one.column,
.one.columns{width:4.66666666667%;}
.two.columns{width:13.3333333333%;}
.three.columns{width:22%;}
.four.columns{width:30.6666666667%;}
.five.columns{width:39.3333333333%;}
.six.columns{width:48%;}
.seven.columns{width:56.6666666667%;}
.eight.columns{width:65.3333333333%;}
.nine.columns{width:74.0%;}
.ten.columns{width:82.6666666667%;}
.eleven.columns{width:91.3333333333%;}
.twelve.columns{width:100%;margin-left:0;}
.one-third.column{width:30.6666666667%;}
.two-thirds.column{width:65.3333333333%;}
.one-half.column{width:48%;}
.offset-by-one.column,
.offset-by-one.columns{margin-left:8.66666666667%;}
.offset-by-two.column,
.offset-by-two.columns{margin-left:17.3333333333%;}
.offset-by-three.column,
.offset-by-three.columns{margin-left:26%;}
.offset-by-four.column,
.offset-by-four.columns{margin-left:34.6666666667%;}
.offset-by-five.column,
.offset-by-five.columns{margin-left:43.3333333333%;}
.offset-by-six.column,
.offset-by-six.columns{margin-left:52%;}
.offset-by-seven.column,
.offset-by-seven.columns{margin-left:60.6666666667%;}
.offset-by-eight.column,
.offset-by-eight.columns{margin-left:69.3333333333%;}
.offset-by-nine.column,
.offset-by-nine.columns{margin-left:78.0%;}
.offset-by-ten.column,
.offset-by-ten.columns{margin-left:86.6666666667%;}
.offset-by-eleven.column,
.offset-by-eleven.columns{margin-left:95.3333333333%;}
.offset-by-one-third.column,
.offset-by-one-third.columns{margin-left:34.6666666667%;}
.offset-by-two-thirds.column,
.offset-by-two-thirds.columns{margin-left:69.3333333333%;}
.offset-by-one-half.column,
.offset-by-one-half.columns{margin-left:52%;}
}
html{font-size:62.5%;}
body{font-size:1.5em;line-height:1.6;font-weight:400;font-family:"Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;color:#222;}
h1, h2, h3, h4, h5, h6{margin-top:0;margin-bottom:2rem;font-weight:300;}
h1{font-size:4.0rem;line-height:1.2;letter-spacing:-.1rem;}
h2{font-size:3.6rem;line-height:1.25;letter-spacing:-.1rem;}
h3{font-size:3.0rem;line-height:1.3;letter-spacing:-.1rem;}
h4{font-size:2.4rem;line-height:1.35;letter-spacing:-.08rem;}
h5{font-size:1.8rem;line-height:1.5;letter-spacing:-.05rem;}
h6{font-size:1.5rem;line-height:1.6;letter-spacing:0;}
@media (min-width:550px){h1{font-size:5.0rem;}
h2{font-size:4.2rem;}
h3{font-size:3.6rem;}
h4{font-size:3.0rem;}
h5{font-size:2.4rem;}
h6{font-size:1.5rem;}
}
p{margin-top:0;}
a{color:#1EAEDB;}
a:hover{color:#0FA0CE;}
.button,
button,
input[type="submit"],
input[type="reset"],
input[type="button"]{display:inline-block;height:38px;padding:0 30px;color:#555;text-align:center;font-size:11px;font-weight:600;line-height:38px;letter-spacing:.1rem;text-transform:uppercase;text-decoration:none;white-space:nowrap;background-color:transparent;border-radius:4px;border:1px solid #bbb;cursor:pointer;box-sizing:border-box;}
.button:hover,
button:hover,
input[type="submit"]:hover,
input[type="reset"]:hover,
input[type="button"]:hover,
.button:focus,
button:focus,
input[type="submit"]:focus,
input[type="reset"]:focus,
input[type="button"]:focus{color:#333;border-color:#888;outline:0;}
.button.button-primary,
button.button-primary,
input[type="submit"].button-primary,
input[type="reset"].button-primary,
input[type="button"].button-primary{color:#FFF;background-color:#33C3F0;border-color:#33C3F0;}
.button.button-primary:hover,
button.button-primary:hover,
input[type="submit"].button-primary:hover,
input[type="reset"].button-primary:hover,
input[type="button"].button-primary:hover,
.button.button-primary:focus,
button.button-primary:focus,
input[type="submit"].button-primary:focus,
input[type="reset"].button-primary:focus,
input[type="button"].button-primary:focus{color:#FFF;background-color:#1EAEDB;border-color:#1EAEDB;}
input[type="email"],
input[type="number"],
input[type="search"],
input[type="text"],
input[type="tel"],
input[type="url"],
input[type="password"],
textarea,
select{height:38px;padding:6px 10px;background-color:#fff;border:1px solid #D1D1D1;border-radius:4px;box-shadow:none;box-sizing:border-box;}
input[type="email"],
input[type="number"],
input[type="search"],
input[type="text"],
input[type="tel"],
input[type="url"],
input[type="password"],
textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;}
textarea{min-height:65px;padding-top:6px;padding-bottom:6px;}
input[type="email"]:focus,
input[type="number"]:focus,
input[type="search"]:focus,
input[type="text"]:focus,
input[type="tel"]:focus,
input[type="url"]:focus,
input[type="password"]:focus,
textarea:focus,
select:focus{border:1px solid #33C3F0;outline:0;}
label,
legend{display:block;margin-bottom:.5rem;font-weight:600;}
fieldset{padding:0;border-width:0;}
input[type="checkbox"],
input[type="radio"]{display:inline;}
label > .label-body{display:inline-block;margin-left:.5rem;font-weight:normal;}
ul{list-style:circle inside;}
ol{list-style:decimal inside;}
ol, ul{padding-left:0;margin-top:0;}
ul ul,
ul ol,
ol ol,
ol ul{margin:1.5rem 0 1.7rem 3rem;font-size:90%;}
li{margin-bottom:1rem;}
code{padding:.2rem .5rem;margin:0 .2rem;font-size:90%;white-space:nowrap;background:#F1F1F1;border:1px solid #E1E1E1;border-radius:4px;}
pre > code{display:block;padding:1rem 1.5rem;white-space:pre;}
th,
td{padding:12px 15px;text-align:left;border-bottom:1px solid #E1E1E1;}
th:first-child,
td:first-child{padding-left:0;}
th:last-child,
td:last-child{padding-right:0;}
button,
.button{margin-bottom:1rem;}
input,
textarea,
select,
fieldset{margin-bottom:1.5rem;}
pre,
blockquote,
dl,
figure,
table,
p,
ul,
ol,
form{margin-bottom:2.5rem;}
.u-full-width{width:100%;box-sizing:border-box;}
.u-max-full-width{max-width:100%;box-sizing:border-box;}
.u-pull-right{float:right;}
.u-pull-left{float:left;}
hr{margin-top:3rem;margin-bottom:3.5rem;border-width:0;border-top:1px solid #E1E1E1;}
.container:after,
.row:after,
.u-cf{content:"";display:table;clear:both;}
@media (min-width:400px){}
@media (min-width:550px){}
@media (min-width:750px){}
@media (min-width:1000px){}
@media (min-width:1200px){}

419
src/css/skeleton.css vendored Normal file
View File

@ -0,0 +1,419 @@
/*
* Skeleton V2.0.4
* Copyright 2014, Dave Gamache
* www.getskeleton.com
* Free to use under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
* 12/29/2014
*/
/* Table of contents
- Grid
- Base Styles
- Typography
- Links
- Buttons
- Forms
- Lists
- Code
- Tables
- Spacing
- Utilities
- Clearing
- Media Queries
*/
/* Grid
*/
.container {
position: relative;
width: 100%;
max-width: 960px;
margin: 0 auto;
padding: 0 20px;
box-sizing: border-box; }
.column,
.columns {
width: 100%;
float: left;
box-sizing: border-box; }
/* For devices larger than 400px */
@media (min-width: 400px) {
.container {
width: 85%;
padding: 0; }
}
/* For devices larger than 550px */
@media (min-width: 550px) {
.container {
width: 80%; }
.column,
.columns {
margin-left: 4%; }
.column:first-child,
.columns:first-child {
margin-left: 0; }
.one.column,
.one.columns { width: 4.66666666667%; }
.two.columns { width: 13.3333333333%; }
.three.columns { width: 22%; }
.four.columns { width: 30.6666666667%; }
.five.columns { width: 39.3333333333%; }
.six.columns { width: 48%; }
.seven.columns { width: 56.6666666667%; }
.eight.columns { width: 65.3333333333%; }
.nine.columns { width: 74.0%; }
.ten.columns { width: 82.6666666667%; }
.eleven.columns { width: 91.3333333333%; }
.twelve.columns { width: 100%; margin-left: 0; }
.one-third.column { width: 30.6666666667%; }
.two-thirds.column { width: 65.3333333333%; }
.one-half.column { width: 48%; }
/* Offsets */
.offset-by-one.column,
.offset-by-one.columns { margin-left: 8.66666666667%; }
.offset-by-two.column,
.offset-by-two.columns { margin-left: 17.3333333333%; }
.offset-by-three.column,
.offset-by-three.columns { margin-left: 26%; }
.offset-by-four.column,
.offset-by-four.columns { margin-left: 34.6666666667%; }
.offset-by-five.column,
.offset-by-five.columns { margin-left: 43.3333333333%; }
.offset-by-six.column,
.offset-by-six.columns { margin-left: 52%; }
.offset-by-seven.column,
.offset-by-seven.columns { margin-left: 60.6666666667%; }
.offset-by-eight.column,
.offset-by-eight.columns { margin-left: 69.3333333333%; }
.offset-by-nine.column,
.offset-by-nine.columns { margin-left: 78.0%; }
.offset-by-ten.column,
.offset-by-ten.columns { margin-left: 86.6666666667%; }
.offset-by-eleven.column,
.offset-by-eleven.columns { margin-left: 95.3333333333%; }
.offset-by-one-third.column,
.offset-by-one-third.columns { margin-left: 34.6666666667%; }
.offset-by-two-thirds.column,
.offset-by-two-thirds.columns { margin-left: 69.3333333333%; }
.offset-by-one-half.column,
.offset-by-one-half.columns { margin-left: 52%; }
}
/* Base Styles
*/
/* NOTE
html is set to 62.5% so that all the REM measurements throughout Skeleton
are based on 10px sizing. So basically 1.5rem = 15px :) */
html {
font-size: 62.5%; }
body {
font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */
line-height: 1.6;
font-weight: 400;
font-family: 'Roboto', "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #222; }
/* Typography
*/
h1, h2, h3, h4, h5, h6 {
font-family: 'Roboto Condensed', Helvetica, Arial, sans-serif;
margin-top: 0;
margin-bottom: 2rem;
font-weight: 300; }
h1 { font-size: 4.0rem; line-height: 1.2; letter-spacing: -.1rem;}
h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; }
h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; }
h4 { font-size: 2.4rem; line-height: 1.35; letter-spacing: -.08rem; font-weight:700;}
h5 { font-size: 1.8rem; line-height: 1.5; letter-spacing: -.05rem; }
h6 { font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; }
/* Larger than phablet */
@media (min-width: 550px) {
h1 { font-size: 5.0rem; }
h2 { font-size: 4.2rem; }
h3 { font-size: 3.6rem; }
h4 { font-size: 3.0rem; }
h5 { font-size: 2.4rem; }
h6 { font-size: 1.5rem; }
}
p {
margin-top: 0; }
/* Links
*/
a {
color: #1EAEDB; }
a:hover {
color: #0FA0CE; }
/* Buttons
*/
.button,
button,
input[type="submit"],
input[type="reset"],
input[type="button"] {
display: inline-block;
height: 38px;
padding: 0 30px;
color: #555;
text-align: center;
font-size: 11px;
font-weight: 600;
line-height: 38px;
letter-spacing: .1rem;
text-transform: uppercase;
text-decoration: none;
white-space: nowrap;
background-color: transparent;
border-radius: 4px;
border: 1px solid #bbb;
cursor: pointer;
box-sizing: border-box; }
.button:hover,
button:hover,
input[type="submit"]:hover,
input[type="reset"]:hover,
input[type="button"]:hover,
.button:focus,
button:focus,
input[type="submit"]:focus,
input[type="reset"]:focus,
input[type="button"]:focus {
color: #333;
border-color: #888;
outline: 0; }
.button.button-primary,
button.button-primary,
input[type="submit"].button-primary,
input[type="reset"].button-primary,
input[type="button"].button-primary {
color: #FFF;
background-color: #33C3F0;
border-color: #33C3F0; }
.button.button-primary:hover,
button.button-primary:hover,
input[type="submit"].button-primary:hover,
input[type="reset"].button-primary:hover,
input[type="button"].button-primary:hover,
.button.button-primary:focus,
button.button-primary:focus,
input[type="submit"].button-primary:focus,
input[type="reset"].button-primary:focus,
input[type="button"].button-primary:focus {
color: #FFF;
background-color: #1EAEDB;
border-color: #1EAEDB; }
/* Forms
*/
input[type="email"],
input[type="number"],
input[type="search"],
input[type="text"],
input[type="tel"],
input[type="url"],
input[type="password"],
textarea,
select {
height: 38px;
padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */
background-color: #fff;
border: 1px solid #D1D1D1;
border-radius: 4px;
box-shadow: none;
box-sizing: border-box; }
/* Removes awkward default styles on some inputs for iOS */
input[type="email"],
input[type="number"],
input[type="search"],
input[type="text"],
input[type="tel"],
input[type="url"],
input[type="password"],
textarea {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none; }
textarea {
min-height: 65px;
padding-top: 6px;
padding-bottom: 6px; }
input[type="email"]:focus,
input[type="number"]:focus,
input[type="search"]:focus,
input[type="text"]:focus,
input[type="tel"]:focus,
input[type="url"]:focus,
input[type="password"]:focus,
textarea:focus,
select:focus {
border: 1px solid #33C3F0;
outline: 0; }
label,
legend {
display: block;
margin-bottom: .5rem;
font-weight: 600; }
fieldset {
padding: 0;
border-width: 0; }
input[type="checkbox"],
input[type="radio"] {
display: inline; }
label > .label-body {
display: inline-block;
margin-left: .5rem;
font-weight: normal; }
/* Lists
*/
ul {
list-style: circle inside; }
ol {
list-style: decimal inside; }
ol, ul {
padding-left: 0;
margin-top: 0; }
ul ul,
ul ol,
ol ol,
ol ul {
margin: 1.5rem 0 1.5rem 3rem;
font-size: 90%; }
li {
margin-bottom: 1rem; }
/* Code
*/
code {
padding: .2rem .5rem;
margin: 0 .2rem;
font-size: 90%;
white-space: nowrap;
background: #F1F1F1;
border: 1px solid #E1E1E1;
border-radius: 4px; }
pre > code {
display: block;
padding: 1rem 1.5rem;
white-space: pre; }
/* Tables
*/
th,
td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #E1E1E1; }
th:first-child,
td:first-child {
padding-left: 0; }
th:last-child,
td:last-child {
padding-right: 0; }
/* Spacing
*/
button,
.button {
margin-bottom: 1rem; }
input,
textarea,
select,
fieldset {
margin-bottom: 1.5rem; }
pre,
blockquote,
dl,
figure,
table,
p,
ul,
ol,
form {
margin-bottom: 2.5rem; }
/* Utilities
*/
.u-full-width {
width: 100%;
box-sizing: border-box; }
.u-max-full-width {
max-width: 100%;
box-sizing: border-box; }
.u-pull-right {
float: right; }
.u-pull-left {
float: left; }
/* Misc
*/
hr {
margin-top: 3rem;
margin-bottom: 3.5rem;
border-width: 0;
border-top: 1px solid #E1E1E1; }
/* Clearing
*/
/* Self Clearing Goodness */
.container:after,
.row:after,
.u-cf {
content: "";
display: table;
clear: both; }
/* Media Queries
*/
/*
Note: The best way to structure the use of media queries is to create the queries
near the relevant code. For example, if you wanted to change the styles for buttons
on small devices, paste the mobile query code up in the buttons section and style it
there.
*/
/* Larger than mobile */
@media (min-width: 400px) {}
/* Larger than phablet (also point when grid becomes active) */
@media (min-width: 550px) {}
/* Larger than tablet */
@media (min-width: 750px) {}
/* Larger than desktop */
@media (min-width: 1000px) {}
/* Larger than Desktop HD */
@media (min-width: 1200px) {}

93
src/css/spinner.scss Normal file
View File

@ -0,0 +1,93 @@
$green: #008744;
$blue: #0fa3ef;
$red: #dc4f43;
$yellow: #ffbe39;
$white: #eee;
$black: #301010;
// scaling... any units
$width: 100px;
body {
background-color: $white;
}
// demo-specific
.showbox {
position: absolute;
top: 40vh;
bottom: 60vh;
left: 0;
right: 0;
padding: 5%;
}
// end demo-specific
.loader {
position: relative;
margin: 0 auto;
width: $width;
&:before {
content: '';
display: block;
padding-top: 100%;
}
}
.circular {
animation: rotate 2s linear infinite;
height: 100%;
transform-origin: center center;
width: 100%;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
.path {
stroke-dasharray: 1, 200;
stroke-dashoffset: 0;
animation: dash 1.5s ease-in-out infinite, color 6s ease-in-out infinite;
stroke-linecap: round;
}
@keyframes rotate {
100% {
transform: rotate(360deg);
}
}
@keyframes dash {
0% {
stroke-dasharray: 1, 200;
stroke-dashoffset: 0;
}
50% {
stroke-dasharray: 89, 200;
stroke-dashoffset: -35px;
}
100% {
stroke-dasharray: 89, 200;
stroke-dashoffset: -124px;
}
}
@keyframes color {
100%,
0% {
stroke: $red;
}
40% {
stroke: $yellow;
}
66% {
stroke: $blue;
}
80%,
90% {
stroke: $black;
}
}

81
src/css/viewport.scss Normal file
View File

@ -0,0 +1,81 @@
.viewport {
width: 100%;
height: 100%;
margin: 0;
}
/* encapsulate the various syntax in helper clases */
/* inspired by http://infrequently.org/2009/08/css-3-progress/ */
/* items flex/expand vertically */
.vbox {
/* previous syntax */
display: -webkit-box;
display: -moz-box;
display: box;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
-ms-box-orient: vertical;
box-orient: vertical;
/* current syntax */
display: -webkit-flex;
display: -moz-flex;
display: -ms-flex;
display: flex;
-webkit-flex-direction: column;
-moz-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.gradient {
/* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#ebf1f6+0,abd3ee+50,89c3eb+51,d5ebfb+100;Blue+Gloss+%234 */
background: #ebf1f6; /* Old browsers */
background: -moz-linear-gradient(top, #ebf1f6 0%, #abd3ee 50%, #89c3eb 51%, #d5ebfb 100%); /* FF3.6-15 */
background: -webkit-linear-gradient(top, #ebf1f6 0%, #abd3ee 50%, #89c3eb 51%, #d5ebfb 100%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(to bottom, #ebf1f6 0%, #abd3ee 50%, #89c3eb 51%, #d5ebfb 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ebf1f6', endColorstr='#d5ebfb', GradientType=0); /* IE6-9 */
}
.backgroundImage {
background-image: url(http://via.placeholder.com/411x823);
}
.appPanel {
/* previous syntax */
-webkit-box-flex: 1;
-moz-box-flex: 1;
-ms-box-flex: 1;
box-flex: 1;
/* current syntax */
-webkit-flex: 1;
-moz-flex: 1;
-ms-flex: 1;
flex: 1;
height: 100vh;
width: 100vw;
overflow-y: auto;
/* background-color: white;*/
}
[data-id~="main"] {
z-index: 0;
position: absolute;
top: 0;
left: 0;
}
[data-id~="routeP"] {
z-index: 1000;
position: absolute;
top: 0;
left: 0;
}

12
src/libs/stations.js Normal file

File diff suppressed because one or more lines are too long

120
src/libs/utils.js Normal file
View File

@ -0,0 +1,120 @@
function partOfDay (timeString, today) {
console.log(new Date());
if (timeString === undefined || timeString === null) timeString = (new Date()).getHours().toString();
if (today === undefined) today = false;
const hours = timeString.substring(0, 2);
let dayBit = '';
console.log('Hours', hours);
if (hours >= 0 && hours < 4)
dayBit = 'Late Night';
else if (hours >= 4 && hours < 7)
dayBit = 'Early Morning';
else if (hours >= 7 && hours < 12)
dayBit = 'Morning';
else if (hours >= 12 && hours < 17)
dayBit = 'Afternoon';
else if (hours < 21)
dayBit = 'Evening';
else dayBit = 'Night';
if (today)
if (dayBit === 'night') {
dayBit = 'tonight';
}
else {
dayBit = `this ${dayBit}`;
}
console.log('partOfDay', dayBit);
return dayBit;
}
function toHour (extra = 0) {
const now = new Date();
return (3600000 - (now.getTime() % 3600000)) + extra;
}
function hourFloor () {
const now = new Date();
return parseInt(~~(now.getTime() / 3600000) * 3600000, 10).toString(32);
}
function minuteFloor () {
const now = new Date();
return parseInt(~~(now.getTime() / 60000) * 60000, 10).toString(32);
}
function distance (lat1, lon1, lat2, lon2) {
const p = 0.017453292519943295; // Math.PI / 180
const c = Math.cos;
const a = 0.5 - c((lat2 - lat1) * p) / 2 +
c(lat1 * p) * c(lat2 * p) *
(1 - c((lon2 - lon1) * p)) / 2;
return 12742 * Math.asin(Math.sqrt(a)); // 2 * R; R = 6371 km
}
/* function splitURL (url) {
} */
const maybePluralize = (count, noun, suffix = 's') =>
`${count} ${noun}${count !== 1 ? suffix : ''}`;
function supportsLocalStorage() {
try {
if (!localStorage)return false;
else return true;
// May only need the above simple test
// - old versions of firefox may cause problem?
// return 'localStorage' in window && window['localStorage']!==null;
}
catch(e) {
return false;
}
}
let LocalStorage = {};
if (supportsLocalStorage())
LocalStorage = {
'save':function ( i, v ) {
localStorage[i] = v;
},
'load':function ( i ) {
return localStorage[i];
},
'exists':function(i) {
return !(typeof(localStorage[i]) === 'undefined');
}
};
else
LocalStorage = {
'save':function ( i, v ) {
document.cookie = `${i }=${ encodeURIComponent(v)}`;
},
'load':function ( i ) {
var s = `; ${ document.cookie };`,
p = s.indexOf(`; ${ i }=`);
if (p < 0)return '';
p = p + i.length + 3;
var p2 = s.indexOf(';', p + 1);
return decodeURIComponent(s.substring(p, p2));
}
};
module.exports = { partOfDay, toHour, hourFloor, distance, maybePluralize, minuteFloor, LocalStorage };

10
src/main.js Normal file
View File

@ -0,0 +1,10 @@
import App from './App.svelte';
const app = new App({
'target': document.body,
'props': {
}
});
export default app;

20
src/pages/Home.svelte Normal file
View File

@ -0,0 +1,20 @@
<script>
import TrainRoute from "../components/TrainRoute.svelte";
</script>
<div class="mui-container">
<TrainRoute destStation="glq" startStation="dbe"/>
<TrainRoute destStation="dbe" startStation="glq"/>
<TrainRoute destStation="glc" startStation="ptk"/>
<TrainRoute destStation="ptk" startStation="dbe"/>
<TrainRoute destStation="glc" startStation="eus"/>
<TrainRoute destStation="eus" startStation="glc"/>
<TrainRoute destStation="pad" startStation="hxx"/>
<TrainRoute destStation="glc" startStation="bhi"/>
<TrainRoute destStation="bhi" startStation="glc"/>
<TrainRoute destStation="dbe" startStation="dmr"/>
<TrainRoute destStation="dmr" startStation="glc"/>
</div>

14
src/pages/NotFound.svelte Normal file
View File

@ -0,0 +1,14 @@
<script>
</script>
<style>
* {
background: #f55a4e;
padding: 3px;
}
</style>
<h2 class="routetitle">NotFound</h2>
<p>Oops, this route doesn't exist!</p>

12
src/pages/Service.svelte Normal file
View File

@ -0,0 +1,12 @@
<script>
</script>
<style>
* {
background: #f55a4e;
padding: 3px;
}
</style>
<span>Service</span>

View File

@ -0,0 +1,41 @@
<script>
import {onMount, onDestroy} from 'svelte';
import TimetableList from "../components/TimetableList.svelte";
import { findStation } from '../libs/stations'
export let params = {};
let fromStationName;
let destStationName;
let fromStation;
let destStation;
onMount(async () => {
console.log('>> Timetable:', params);
fromStation = params.fromStation;
destStation = params.destStation;
fromStationName = findStation(fromStation);
destStationName = findStation(destStation);
});
onDestroy(async () => {
console.log('>> onDestroy Timetable')
});
</script>
<style>
</style>
<div class="mui--appbar-height"></div>
<div class="mui-container">
<div>
<div class="mui--text-center mui--text-accent">{fromStationName} TO {destStationName}</div>
<TimetableList {fromStation} {destStation}/>
<!--<timetable-list :fromStation="$route.params.fromStation" :destStation="$route.params.destStation"/>-->
</div>
</div>

21
src/routes.js Normal file
View File

@ -0,0 +1,21 @@
/**
* Created by WebStorm.
* User: martin
* Date: 19/04/2020
* Time: 21:19
*/
// import { wrap } from 'svelte-spa-router';
import Home from './pages/Home.svelte';
import Service from './pages/Service.svelte';
import Timetable from './pages/Timetable.svelte';
import NotFound from './pages/NotFound.svelte';
const routes = new Map();
routes.set('/', Home);
routes.set('/timetable/:fromStation/:destStation', Timetable);
routes.set('/service/:serviceId', Service);
routes.set('*', NotFound);
export default routes;