diff options
author | Mark Powers <mark@marks.kitchen> | 2024-07-14 16:17:59 -0500 |
---|---|---|
committer | Mark Powers <mark@marks.kitchen> | 2024-07-14 16:17:59 -0500 |
commit | 0e742a485f3fa7d35d26b05980a293b5760e8418 (patch) | |
tree | 97510b5e1979f7e02dbcb17ccbc699c4f97e63f2 /src/pages |
Diffstat (limited to 'src/pages')
-rw-r--r-- | src/pages/BookPage.vue | 69 | ||||
-rw-r--r-- | src/pages/ErrorNotFound.vue | 31 | ||||
-rw-r--r-- | src/pages/FormPage.vue | 116 | ||||
-rw-r--r-- | src/pages/IndexPage.vue | 174 | ||||
-rw-r--r-- | src/pages/WorkoutPage.vue | 36 |
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> |