koro

an event time scheduler
git clone https://tilde.team/~marisa/repo/koro.git
Log | Files | Refs | README | LICENSE

commit 7a44b1a5018d8bad0967dba427804835a873b988
parent 69f57444b3f36400638652e92bf11b1b5e69fb7f
Author: mokou <mokou@posteo.de>
Date:   Thu, 21 May 2020 02:16:19 +0200

chore: Lint

Diffstat:
A.prettierignore | 2++
MREADME.md | 10+++-------
Mpackage.json | 2+-
Mpostcss.config.js | 5+----
Msrc/App.svelte | 22++++++++++++----------
Msrc/components/DateTimeGrid.svelte | 90+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Msrc/main.css | 25+++++++++++++------------
Msrc/main.js | 8++++----
Asrc/pages/Event.svelte | 5+++++
Msrc/pages/Index.svelte | 88++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Mtailwind.config.js | 9+++------
Mwebpack.config.js | 49++++++++++++++++++++++++-------------------------
12 files changed, 173 insertions(+), 142 deletions(-)

diff --git a/.prettierignore b/.prettierignore @@ -0,0 +1,2 @@ +public/ +node_modules/ diff --git a/README.md b/README.md @@ -1,4 +1,4 @@ -*Looking for a shareable component template? Go here --> [sveltejs/component-template](https://github.com/sveltejs/component-template)* +_Looking for a shareable component template? Go here --> [sveltejs/component-template](https://github.com/sveltejs/component-template)_ --- @@ -13,8 +13,7 @@ npx degit sveltejs/template svelte-app cd svelte-app ``` -*Note that you will need to have [Node.js](https://nodejs.org) installed.* - +_Note that you will need to have [Node.js](https://nodejs.org) installed._ ## Get started @@ -35,7 +34,6 @@ Navigate to [localhost:5000](http://localhost:5000). You should see your app run 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: @@ -46,18 +44,16 @@ 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: +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) diff --git a/package.json b/package.json @@ -5,7 +5,7 @@ "scripts": { "build": "webpack", "start": "webpack-dev-server", - "lint": "prettier --write ." + "lint": "prettier --write --no-semi ." }, "dependencies": { "accessible-autocomplete": "^2.0.2", diff --git a/postcss.config.js b/postcss.config.js @@ -1,6 +1,3 @@ module.exports = { - plugins: [ - require('tailwindcss'), - require('cssnano') - ] + plugins: [require("tailwindcss"), require("cssnano")], } diff --git a/src/App.svelte b/src/App.svelte @@ -1,20 +1,22 @@ <script> - import navaid from "navaid"; - import Index from "./pages/Index.svelte"; + import navaid from "navaid" + import Index from "./pages/Index.svelte" + import Event from "./pages/Event.svelte" - export let router = navaid(); - let route; - let routeParams; + export let router = navaid() + let route + let routeParams - router.on("/", setRoute(Index)); + router.on("/", setRoute(Index)) + router.on("/:id", setRoute(Event)) - router.listen(); + router.listen() function setRoute(r) { return (params) => { - route = r; - routeParams = params; - }; + route = r + routeParams = params + } } </script> diff --git a/src/components/DateTimeGrid.svelte b/src/components/DateTimeGrid.svelte @@ -1,6 +1,6 @@ <script> - import day from 'dayjs' - import relativeTime from 'dayjs/plugin/relativeTime' + import day from "dayjs" + import relativeTime from "dayjs/plugin/relativeTime" day.extend(relativeTime) export let startDate @@ -14,43 +14,43 @@ let view = [0, 5] initDays(day(startDate)) - function initDays (start) { + function initDays(start) { let first = start if (start.date() === day(startDate).date()) { day1 = day(startDate) - first = day1.add(30, 'minutes').startOf('hour') + first = day1.add(30, "minutes").startOf("hour") } else { day1 = start } datesDay1 = [first] let indexDay1 = first - while (indexDay1.add(30, 'minutes').date() === day1.date()) { - indexDay1 = indexDay1.add(30, 'minutes') + while (indexDay1.add(30, "minutes").date() === day1.date()) { + indexDay1 = indexDay1.add(30, "minutes") datesDay1.push(indexDay1) } - day2 = day1.add(1, 'days').startOf('day') + day2 = day1.add(1, "days").startOf("day") datesDay2 = [day2] let indexDay2 = day2 - while (indexDay2.add(30, 'minutes').date() === day2.date()) { - indexDay2 = indexDay2.add(30, 'minutes') + while (indexDay2.add(30, "minutes").date() === day2.date()) { + indexDay2 = indexDay2.add(30, "minutes") datesDay2.push(indexDay2) } - day3 = day2.add(1, 'days').startOf('day') + day3 = day2.add(1, "days").startOf("day") datesDay3 = [day3] let indexDay3 = day3 - while (indexDay3.add(30, 'minutes').date() === day3.date()) { - indexDay3 = indexDay3.add(30, 'minutes') + while (indexDay3.add(30, "minutes").date() === day3.date()) { + indexDay3 = indexDay3.add(30, "minutes") datesDay3.push(indexDay3) } } - function previousDay () { + function previousDay() { if (day1.date() !== day(startDate).date()) { - initDays(day1.subtract(1, 'day').startOf('day')) + initDays(day1.subtract(1, "day").startOf("day")) } } - function addOrRemove (date) { + function addOrRemove(date) { if (selected.includes(date.toISOString())) { let c = selected c.splice(selected.indexOf(date.toISOString()), 1) @@ -61,8 +61,8 @@ console.log(selected) } - function nextDay () { - initDays(day1.add(1, 'day').startOf('day')) + function nextDay() { + initDays(day1.add(1, "day").startOf("day")) } </script> @@ -70,15 +70,25 @@ <div class="text-center hover:cursor-pointer" on:click={previousDay}> {day1.date() === day(startDate).date() ? '' : '▲'} </div> - <div class="text-center hover:cursor-pointer" on:click={() => view = view[0] !== 0 ? [view[0] - 1, view[1] - 1] : view}> + <div + class="text-center hover:cursor-pointer" + on:click={() => (view = view[0] !== 0 ? [view[0] - 1, view[1] - 1] : view)}> {view[0] !== 0 ? '‹' : ''} </div> - <div class="col-span-3"></div> - <div class="text-center hover:cursor-pointer" on:click={() => view = [view[0] + 1, view[1] + 1]}>›</div> - <div class="font-bold">{day1.date() === day(startDate).date() ? 'today' : day1.endOf('day').fromNow()}</div> + <div class="col-span-3" /> + <div + class="text-center hover:cursor-pointer" + on:click={() => (view = [view[0] + 1, view[1] + 1])}> + › + </div> + <div class="font-bold"> + {day1.date() === day(startDate).date() ? 'today' : day1 + .endOf('day') + .fromNow()} + </div> {#if datesDay1.slice(view[0], view[1]).length < 5} {#each new Array(5 - datesDay1.slice(view[0], view[1]).length) as a} - <div></div> + <div /> {/each} {/if} {#each datesDay1.slice(view[0], view[1]) as t} @@ -86,39 +96,51 @@ class="text-center time hover:cursor-pointer" class:bg-purple-600={selected.includes(t.toISOString())} class:text-white={selected.includes(t.toISOString())} - on:click={() => addOrRemove(t)} - >{t.format('hh:mm')}</div> + on:click={() => addOrRemove(t)}> + {t.format('hh:mm')} + </div> {/each} - <div>{day2.date() === day(startDate).date() ? 'today' : day2.endOf('day').fromNow()}</div> + <div> + {day2.date() === day(startDate).date() ? 'today' : day2 + .endOf('day') + .fromNow()} + </div> {#each datesDay2.slice(view[0], view[1]) as t} <div class="text-center time hover:cursor-pointer" class:bg-purple-600={selected.includes(t.toISOString())} class:text-white={selected.includes(t.toISOString())} - on:click={() => addOrRemove(t)} - >{t.format('hh:mm')}</div> + on:click={() => addOrRemove(t)}> + {t.format('hh:mm')} + </div> {/each} - <div>{day3.date() === day(startDate).date() ? 'today' : day3.endOf('day').fromNow()}</div> + <div> + {day3.date() === day(startDate).date() ? 'today' : day3 + .endOf('day') + .fromNow()} + </div> {#each datesDay3.slice(view[0], view[1]) as t} <div class="text-center time hover:cursor-pointer" class:bg-purple-600={selected.includes(t.toISOString())} class:text-white={selected.includes(t.toISOString())} - on:click={() => addOrRemove(t)} - >{t.format('hh:mm')}</div> + on:click={() => addOrRemove(t)}> + {t.format('hh:mm')} + </div> {/each} - <div class="text-center hover:cursor-pointer" on:click={nextDay}> - ▼ - </div> + <div class="text-center hover:cursor-pointer" on:click={nextDay}>▼</div> </div> <div class="mt-2"> {selected.length} potential time{selected.length === 1 ? '' : 's'} selected: <ul class="list-disc"> {#each selected as s} - <li><span class="font-bold">{day(s).format('DD/MM/YYYY hh:mm')}</span> ({day(s).fromNow()})</li> + <li> + <span class="font-bold">{day(s).format('DD/MM/YYYY hh:mm')}</span> + ({day(s).fromNow()}) + </li> {/each} </ul> </div> diff --git a/src/main.css b/src/main.css @@ -1,17 +1,18 @@ @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-style: normal; font-weight: 400; - src: local('Inter Regular'), local('Inter-Regular'), - url('../fonts/Inter-Regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ - url('../fonts/Inter-Regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + src: local("Inter Regular"), local("Inter-Regular"), + url("../fonts/Inter-Regular.woff2") format("woff2"), + /* Chrome 26+, Opera 23+, Firefox 39+ */ url("../fonts/Inter-Regular.woff") + format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ } -@import 'tailwindcss/base'; -@import 'tailwindcss/components'; +@import "tailwindcss/base"; +@import "tailwindcss/components"; body { - font-family: 'Inter'; + font-family: "Inter"; } input { @@ -19,15 +20,15 @@ input { background-color: #fff; border-color: #d2d6dc; border-width: 1px; - border-radius: .375rem; - padding: .5rem .75rem; + border-radius: 0.375rem; + padding: 0.5rem 0.75rem; font-size: 1rem; line-height: 1.5; } .btn { @apply px-3 py-2 font-bold bg-purple-600 text-white border-purple-600 rounded-sm; - font-family: 'Inter'; + font-family: "Inter"; } .btn:not(:disabled):active { @@ -64,7 +65,7 @@ input { input:focus { outline: none; - box-shadow: 0 0 0 3px rgba(164, 202, 254, .45); + box-shadow: 0 0 0 3px rgba(164, 202, 254, 0.45); border-color: #a4cafe; } @@ -74,4 +75,4 @@ input:focus { } } -@import 'tailwindcss/utilities'; +@import "tailwindcss/utilities"; diff --git a/src/main.js b/src/main.js @@ -1,11 +1,11 @@ -import App from './App.svelte' -import './main.css' +import App from "./App.svelte" +import "./main.css" const app = new App({ target: document.body, props: { - name: 'world' - } + name: "world", + }, }) export default app diff --git a/src/pages/Event.svelte b/src/pages/Event.svelte @@ -0,0 +1,5 @@ +<script> + +</script> + +<h1>E!</h1> diff --git a/src/pages/Index.svelte b/src/pages/Index.svelte @@ -1,60 +1,60 @@ <script> - import PouchDB from 'pouchdb-browser' - import autocomplete from 'accessible-autocomplete' - import search from 'fuzzysearch' - import { nanoid } from 'nanoid' - import { onMount } from 'svelte' - import DateTimeGrid from '../components/DateTimeGrid.svelte' + import PouchDB from "pouchdb-browser" + import autocomplete from "accessible-autocomplete" + import search from "fuzzysearch" + import { nanoid } from "nanoid" + import { onMount } from "svelte" + import DateTimeGrid from "../components/DateTimeGrid.svelte" let submitting = false - let errorFlash = '' + let errorFlash = "" let durationInput = null let durationsList = [ - '15 minutes', - '30 minutes', - '45 minutes', - '1 hour', - '2 hours', - '3 hours', - '4 hours', - '5 hours' + "15 minutes", + "30 minutes", + "45 minutes", + "1 hour", + "2 hours", + "3 hours", + "4 hours", + "5 hours", ] let event = { _id: nanoid(), - name: '', - duration: '', - times: [] + name: "", + duration: "", + times: [], } - async function submitForm () { - errorFlash = '' + async function submitForm() { + errorFlash = "" submitting = true if (!event.name) { - errorFlash = 'Please set a name for your event!' + errorFlash = "Please set a name for your event!" submitting = false return } if (!event.duration) { - errorFlash = 'Please set a duration for your event!' + errorFlash = "Please set a duration for your event!" submitting = false return } if (!durationsList.includes(event.duration)) { console.log(event) - errorFlash = 'The duration must be picked from the provided list!' + errorFlash = "The duration must be picked from the provided list!" submitting = false return } if (event.times.length === 0) { - errorFlash = 'Please pick at least one event time!' + errorFlash = "Please pick at least one event time!" submitting = false return } - const db = new PouchDB('koro') + const db = new PouchDB("koro") try { const res = await db.put(event) console.log(res) @@ -63,44 +63,54 @@ } } - function durationSource (query, cb) { + function durationSource(query, cb) { if (durationsList.includes(query)) cb([]) - const filtered = durationsList.filter(d => search(query, d)) + const filtered = durationsList.filter((d) => search(query, d)) cb(filtered) } onMount(() => { autocomplete({ - element: document.querySelector('#duration-mount'), - id: 'duration', + element: document.querySelector("#duration-mount"), + id: "duration", source: durationSource, confirmOnBlur: false, - onConfirm: opt => { + onConfirm: (opt) => { event.duration = opt console.log(event) - } + }, }) }) </script> <h1 class="text-5xl font-serif font-extrabold">koro</h1> <p class="text-2xl font-medium max-w-xl leading-normal"> - An event time planning site for the rest of us. Use this to find a timeslot for your next - meeting, party, raid, whatever you want. It automatically supports the user's timezone - and works locally, too. + An event time planning site for the rest of us. Use this to find a timeslot + for your next meeting, party, raid, whatever you want. It automatically + supports the user's timezone and works locally, too. </p> <form class="max-w-xl mt-10" on:submit|preventDefault={submitForm}> {#if errorFlash} - <div class="w-full bg-red-100 px-3 py-2 border rounded border-red-400 text-red-600 my-5"> + <div + class="w-full bg-red-100 px-3 py-2 border rounded border-red-400 + text-red-600 my-5"> {errorFlash} </div> {/if} <label for="name" class="font-bold text-gray-600">Your event's name</label> - <input name="name" type="text" bind:value={event.name} placeholder="Raid with the boys" /> - <label for="duration" class="font-bold text-gray-600 mt-3">Duration of the event</label> - <div id="duration-mount" class="mb-5"></div> + <input + name="name" + type="text" + bind:value={event.name} + placeholder="Raid with the boys" /> + <label for="duration" class="font-bold text-gray-600 mt-3"> + Duration of the event + </label> + <div id="duration-mount" class="mb-5" /> <label class="font-bold text-gray-600">Event start times</label> <DateTimeGrid startDate={new Date()} bind:selected={event.times} /> - <button class="btn mt-5" type="submit" disabled={submitting}>Create event</button> + <button class="btn mt-5" type="submit" disabled={submitting}> + Create event + </button> </form> diff --git a/tailwind.config.js b/tailwind.config.js @@ -1,9 +1,6 @@ module.exports = { - purge: [ - './src/**/*.svelte', - './src/**/*.js' - ], + purge: ["./src/**/*.svelte", "./src/**/*.js"], variants: { - cursor: ['hover'] - } + cursor: ["hover"], + }, } diff --git a/webpack.config.js b/webpack.config.js @@ -1,54 +1,53 @@ -const CssExtractPlugin = require('mini-css-extract-plugin') -const TerserWebpackPlugin = require('terser-webpack-plugin') -const path = require('path') +const CssExtractPlugin = require("mini-css-extract-plugin") +const TerserWebpackPlugin = require("terser-webpack-plugin") +const path = require("path") -const prod = process.env.NODE_ENV !== 'development' +const prod = process.env.NODE_ENV !== "development" module.exports = { - name: 'bundle', + name: "bundle", entry: { - main: './src/main.js' + main: "./src/main.js", }, output: { - filename: '[name].js', - path: path.resolve(process.cwd(), 'public/build') + filename: "[name].js", + path: path.resolve(process.cwd(), "public/build"), }, - mode: prod ? 'production' : 'development', + mode: prod ? "production" : "development", devServer: { - contentBase: path.join(process.cwd(), 'public'), + contentBase: path.join(process.cwd(), "public"), compress: true, - port: 3000 + port: 3000, + historyApiFallback: true, }, - devtool: !prod && 'source-map', + devtool: !prod && "source-map", optimization: prod && { - minimizer: [new TerserWebpackPlugin({})] + minimizer: [new TerserWebpackPlugin({})], }, resolve: { alias: { - svelte: path.resolve('node_modules', 'svelte') + svelte: path.resolve("node_modules", "svelte"), }, - extensions: ['.mjs', '.js', '.svelte'], - mainFields: ['svelte', 'browser', 'module', 'main'] + extensions: [".mjs", ".js", ".svelte"], + mainFields: ["svelte", "browser", "module", "main"], }, module: { rules: [ { test: /\.(html|svelte)$/, exclude: /node_modules/, - use: 'svelte-loader' + use: "svelte-loader", }, { test: /\.css$/, exclude: /node_modules/, use: [ { loader: CssExtractPlugin.loader }, - { loader: 'css-loader', options: { url: false, importLoaders: 1 } }, - { loader: 'postcss-loader' } - ] - } - ] + { loader: "css-loader", options: { url: false, importLoaders: 1 } }, + { loader: "postcss-loader" }, + ], + }, + ], }, - plugins: [ - new CssExtractPlugin() - ] + plugins: [new CssExtractPlugin()], }