aboutsummaryrefslogtreecommitdiff
path: root/src/pages
diff options
context:
space:
mode:
Diffstat (limited to 'src/pages')
-rw-r--r--src/pages/BookPage.vue69
-rw-r--r--src/pages/ErrorNotFound.vue31
-rw-r--r--src/pages/FormPage.vue116
-rw-r--r--src/pages/IndexPage.vue174
-rw-r--r--src/pages/WorkoutPage.vue36
5 files changed, 426 insertions, 0 deletions
diff --git a/src/pages/BookPage.vue b/src/pages/BookPage.vue
new file mode 100644
index 0000000..3172239
--- /dev/null
+++ b/src/pages/BookPage.vue
@@ -0,0 +1,69 @@
+<template>
+ <q-page class="row q-pa-md q-gutter-md column">
+ <q-card v-for="(book, index) in books" :key="index">
+ <q-card-section>
+ {{ book.title }} - {{ book.in_library }} - {{ book.lcc }}
+ <q-btn label="Edit" color="primary" @click="books_dialog = true; active_book = book" size="large"/>
+ <ul>
+ <li v-for="(datapoint, index2) in book.data" :key="index2">
+ {{ datapoint.created }} -
+ {{ datapoint.pages }}
+ </li>
+ </ul>
+ </q-card-section>
+ </q-card>
+ <q-dialog v-model="books_dialog" persistent width="50%">
+ <q-card>
+ <q-card-section>
+ <q-form @submit.prevent="submit_book">
+ <q-input label="Title" v-model="active_book.title"></q-input>
+ <q-toggle label="In Library" v-model="active_book.in_library"></q-toggle>
+ <q-input label="LCC" v-model="active_book.lcc"></q-input>
+ <q-btn label="Submit" type="submit" color="primary" size="large"/>
+ </q-form>
+ </q-card-section>
+ </q-card>
+ </q-dialog>
+ </q-page>
+</template>
+
+<script>
+import { defineComponent, ref } from 'vue'
+import {
+ get_books,
+ get_book_datapoint,
+ edit_book,
+} from '../api.js'
+
+export default defineComponent({
+ name: 'BookPage',
+ setup(){
+ let books = ref([])
+ get_books().then(json => {
+ books.value = json
+ books.value.forEach(book => {
+ book.data = []
+ })
+ get_book_datapoint().then(json => {
+ json.forEach(datapoint => {
+ let book = books.value.find(book => {
+ return book.id == datapoint.book_id
+ })
+ book?.data.push(datapoint)
+ })
+ })
+ })
+ let books_dialog = ref(false)
+ let active_book = ref(null)
+ return {
+ books: books,
+ books_dialog,
+ active_book,
+ submit_book(){
+ edit_book(active_book.value)
+ books_dialog.value = false
+ }
+ }
+ }
+})
+</script>
diff --git a/src/pages/ErrorNotFound.vue b/src/pages/ErrorNotFound.vue
new file mode 100644
index 0000000..c1c178b
--- /dev/null
+++ b/src/pages/ErrorNotFound.vue
@@ -0,0 +1,31 @@
+<template>
+ <div class="fullscreen bg-blue text-white text-center q-pa-md flex flex-center">
+ <div>
+ <div style="font-size: 30vh">
+ 404
+ </div>
+
+ <div class="text-h2" style="opacity:.4">
+ Oops. Nothing here...
+ </div>
+
+ <q-btn
+ class="q-mt-xl"
+ color="white"
+ text-color="blue"
+ unelevated
+ to="/"
+ label="Go Home"
+ no-caps
+ />
+ </div>
+ </div>
+</template>
+
+<script>
+import { defineComponent } from 'vue'
+
+export default defineComponent({
+ name: 'ErrorNotFound'
+})
+</script>
diff --git a/src/pages/FormPage.vue b/src/pages/FormPage.vue
new file mode 100644
index 0000000..c3040e2
--- /dev/null
+++ b/src/pages/FormPage.vue
@@ -0,0 +1,116 @@
+<template>
+ <q-page class="row q-pa-md q-gutter-md column">
+ <q-card v-for="(form, index) in forms" :key="index">
+ <q-card-section>
+ <div>
+ {{ form.prompt }}
+ </div>
+ <div>
+ {{ form.type }}
+ </div>
+ <div v-if="form.type == 'multiple_select'">
+ <ul>
+ <li v-for="item in form.extra" :key="item.id">
+ {{ item.id }}
+ </li>
+ <li>
+ <q-form @submit.prevent="form.new_choice" class="row">
+ <q-input
+ label="New choice" type="text"
+ class="col-10"
+ v-model="form.new_choice_value"
+ ></q-input>
+ <q-btn label="Submit" type="submit" color="primary"/>
+ </q-form>
+ </li>
+ </ul>
+ </div>
+ <div v-if="form.type == 'range'">
+ <div>min: {{ form.extra.min }}</div>
+ <div>max: {{ form.extra.max }}</div>
+ </div>
+ </q-card-section>
+ </q-card>
+ <q-card>
+ <q-card-section>
+ <p>New form</p>
+ <q-form class="row" @submit.prevent="submit_new_form">
+ <q-select
+ label="Type"
+ class="col-12"
+ :options="options"
+ v-model="new_form_data.type"
+ ></q-select>
+ <q-input
+ label="Prompt" type="text"
+ class="col-12"
+ v-model="new_form_data.prompt"
+ ></q-input>
+ <q-input
+ label="Prompt Id" type="text"
+ class="col-12"
+ v-model="new_form_data.prompt_id"
+ ></q-input>
+ <q-input v-if="new_form_data.type == 'range'"
+ label="Min" type="number" class="col-12"
+ v-model="new_form_data.extra.min"
+ ></q-input>
+ <q-input v-if="new_form_data.type == 'range'"
+ label="Max" type="number" class="col-12"
+ v-model="new_form_data.extra.max"
+ ></q-input>
+ <q-btn label="Submit" type="submit" color="primary"/>
+ </q-form>
+ </q-card-section>
+ </q-card>
+ </q-page>
+</template>
+
+<script>
+import { defineComponent, ref } from 'vue'
+import {
+ get_forms,
+ create_option,
+ create_form,
+} from '../api.js'
+
+export default defineComponent({
+ name: 'FormPage',
+ setup(){
+ let forms = ref([])
+ get_forms().then(json => {
+ forms.value = json
+ forms.value.forEach(form => {
+ form.new_choice_value = ""
+ form.new_choice = function(){
+ create_option(form, form.new_choice_value)
+ }
+ })
+ })
+ let new_form_data = ref({
+ "extra": {},
+ })
+ return {
+ forms,
+ options: [
+ "multiple_select",
+ "number",
+ "range",
+ "text",
+ ],
+ new_form_data,
+ submit_new_form(){
+ if(new_form_data.value.type && new_form_data.value.prompt && new_form_data.value.prompt_id){
+ if(new_form_data.value.type == 'range' && new_form_data.value.extra.min && new_form_data.value.extra.max) {
+ console.log(new_form_data.value)
+ create_form(new_form_data.value)
+ } else if (new_form_data.value.type != 'range'){
+ new_form_data.value.extra = []
+ create_form(new_form_data.value)
+ }
+ }
+ },
+ }
+ }
+})
+</script>
diff --git a/src/pages/IndexPage.vue b/src/pages/IndexPage.vue
new file mode 100644
index 0000000..b97d68e
--- /dev/null
+++ b/src/pages/IndexPage.vue
@@ -0,0 +1,174 @@
+<template>
+ <q-page class="row q-pa-md q-gutter-md">
+ <div>
+ <q-btn label="Log Books" color="primary" @click="books_dialog = true" size="large"/>
+ </div>
+ <q-dialog v-model="books_dialog" persistent full-width>
+ <q-card>
+ <q-form @submit.prevent="submit_books">
+ <q-card-section
+ v-for="(book, index) in books" :key="index" class="row">
+ <q-input
+ :label="book.title" type="number"
+ class="col-10"
+ v-model="book_form_data[book.id].progress"
+ ></q-input>
+ <q-toggle
+ v-model="book_form_data[book.id].completed"
+ label="Completed?"
+ class="col-2"
+ />
+ </q-card-section>
+ <q-card-section>
+ <div class="row">
+ <q-input
+ label="New book" type="text"
+ class="col-10"
+ v-model="new_book_data.name"
+ ></q-input>
+ <q-btn label="Submit" @click="submit_book()" color="primary" size="large"/>
+ </div>
+ </q-card-section>
+ <q-card-actions align="right" class="text-primary">
+ <q-btn label="Submit" type="submit" color="primary" size="large"/>
+ <q-btn flat label="Cancel" v-close-popup size="large"/>
+ </q-card-actions>
+ </q-form>
+ </q-card>
+ </q-dialog>
+ <q-form class="q-gutter-md col-11" @submit.prevent="submit">
+ <div v-for="(form, index) in forms" :key="index">
+ <template v-if="form.type === 'multiple_select'">
+ <div class="row">
+ <q-select
+ :label="form.prompt"
+ filled
+ v-model="form_data[form.prompt_id]"
+ use-input
+ use-chips
+ multiple
+ input-debounce="0"
+ :options="form.filter_options"
+ @filter="form.filterFn"
+ @new-value="form.createValue"
+ class="col-12"
+ ></q-select>
+ </div>
+ </template>
+ <template v-else-if="form.type === 'number'">
+ <q-input
+ :label="form.prompt"
+ type="number"
+ v-model="form_data[form.prompt_id]"
+ ></q-input>
+ </template>
+ <template v-else-if="form.type === 'range'">
+ <span>{{ form.prompt }}</span>
+ <q-slider
+ :min="form.extra.min"
+ :max="form.extra.max"
+ v-model="form_data[form.prompt_id]"
+ ></q-slider>
+ </template>
+ <template v-else-if="form.type === 'text'">
+ <!-- TODO autofill -->
+ <q-input
+ :label="form.prompt"
+ type="text"
+ v-model="form_data[form.prompt_id]"
+ ></q-input>
+ </template>
+ <template v-else-if="form.type === 'textarea'">
+ <q-input
+ :label="form.prompt"
+ type="text"
+ v-model="form_data[form.prompt_id]"
+ ></q-input>
+ </template>
+ </div>
+ <q-btn label="Submit" type="submit" color="primary" size="large"/>
+ </q-form>
+ </q-page>
+</template>
+
+<script>
+import { defineComponent, ref } from 'vue'
+import {
+ get_forms,
+ get_books,
+ submit_data,
+ submit_book_data,
+ create_option,
+ complete_book,
+ create_book_datapoint,
+ create_book,
+} from '../api.js'
+
+export default defineComponent({
+ name: 'IndexPage',
+ setup() {
+ let forms = ref([])
+ let form_data = ref({})
+ get_forms().then(json => {
+ forms.value = json
+ forms.value.forEach(f => {
+ if(f.type === 'multiple_select'){
+ form_data.value[f.prompt_id] = []
+ let str_options = f.extra.map(o => o.id)
+ f.filter_options = str_options
+ f.filterFn = function(val, update) {
+ update(() => {
+ if (val === '') {
+ f.filter_options = str_options
+ } else {
+ const needle = val.toLowerCase()
+ f.filter_options = str_options.filter(
+ v => v.toLowerCase().indexOf(needle) > -1
+ )
+ }
+ })
+ }
+ f.createValue = function(val, done) {
+ if (val.length > 1) {
+ if (!str_options.includes(val)) {
+ create_option(f, val)
+ done(val, 'add-unique')
+ }
+ }
+ }
+ }
+ })
+ })
+
+ let books = ref([])
+ let book_form_data = ref({})
+ let new_book_data = ref({})
+ get_books().then(json => {
+ books.value = json
+ books.value.forEach( book => {
+ book_form_data.value[book.id] = {
+ "completed": false,
+ "progress": "",
+ }
+ })
+ })
+ let books_dialog = ref(false)
+
+ return {
+ forms, form_data,
+ books, book_form_data, new_book_data,
+ books_dialog,
+ submit_book(){
+ create_book(new_book_data.value.name)
+ },
+ submit(){
+ submit_data(forms.value, form_data.value)
+ },
+ submit_books(){
+ submit_book_data(book_form_data.value)
+ books_dialog.value = false
+ }
+ }
+ }
+})
+</script>
diff --git a/src/pages/WorkoutPage.vue b/src/pages/WorkoutPage.vue
new file mode 100644
index 0000000..8a7f59f
--- /dev/null
+++ b/src/pages/WorkoutPage.vue
@@ -0,0 +1,36 @@
+<template>
+ <q-page class="row q-pa-md q-gutter-md column">
+ <q-card v-for="(workout, index) in history" :key="index">
+ <q-card-section>
+ {{ workout.type }}
+ {{ workout.total_time }} minutes
+ {{ workout.distance }} miles
+ {{ workout.calories }} calories
+ </q-card-section>
+ </q-card>
+ </q-page>
+</template>
+
+<script>
+import { defineComponent, ref } from 'vue'
+import {
+} from '../api.js'
+
+export default defineComponent({
+ name: 'WorkoutPage',
+ setup(){
+ let history = ref([
+ {
+ "created": Date.now(),
+ "type": "stationary bike",
+ "total_time": 29,
+ "distance": 8.0,
+ "calories": 270,
+ },
+ ])
+ return {
+ history
+ }
+ }
+})
+</script>