Skip to content

Commit

Permalink
Add a Q&A component
Browse files Browse the repository at this point in the history
  • Loading branch information
ajuvonen committed Sep 11, 2024
1 parent ba966f1 commit 63ad181
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 12 deletions.
9 changes: 9 additions & 0 deletions src/assets/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@
}
}

main a {
@apply underline rounded-md;
@apply text-slate-300;
&:hover,
&:focus {
@apply text-slate-50;
}
}

html {
@apply h-full;
scrollbar-width: none;
Expand Down
67 changes: 67 additions & 0 deletions src/components/QAComponent.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<script lang="ts" setup>
import {Disclosure, DisclosureButton, DisclosurePanel} from '@headlessui/vue';
import IconComponent from './IconComponent.vue';
const questions = [
'appPurpose',
'studyDetails',
'isItFree',
'isMyDataSafe',
'contact',
'whatCounts',
'categories',
];
const keysWithLinks = ['contact', 'studyDetails'];
</script>
<template>
<div class="flex-container flex-col min-h-0">
<label class="uppercase text-xs">{{ $t('qa.title') }}</label>
<div class="flex-container flex-col has-scroll">
<Disclosure v-for="key in questions" :key="key" v-slot="{open}">
<DisclosureButton class="QA__button">
<span>{{ $t(`qa.${key}.title`) }}</span>
<IconComponent :class="open ? 'rotate-180 transform' : ''" icon="chevron" />
</DisclosureButton>
<transition
enter-active-class="transition duration-100 ease-out"
enter-from-class="transform h-0 opacity-0"
enter-to-class="transform h-full opacity-100"
leave-active-class="transition duration-75 ease-out"
leave-from-class="transform h-full opacity-100"
leave-to-class="transform h-0 opacity-0"
>
<DisclosurePanel class="QA__panel">
<i18n-t :keypath="`qa.${key}.text`" tag="span" scope="global">
<a
v-if="keysWithLinks.includes(key)"
:href="$t(`qa.${key}.link.url`)"
target="_blank"
noreferrer
noopener
>{{ $t(`qa.${key}.link.text`) }}</a
>
</i18n-t>
</DisclosurePanel>
</transition>
</Disclosure>
</div>
</div>
</template>
<style lang="scss" scoped>
.QA__button {
letter-spacing: 1px;
@apply w-full cursor-pointer button-like;
@apply flex-container justify-between;
@apply bg-sky-500;
&:hover,
&:focus {
@apply bg-sky-600;
}
}
.QA__panel {
@apply p-2;
}
</style>
41 changes: 40 additions & 1 deletion src/components/__tests__/__snapshots__/SettingsView.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,46 @@ exports[`SettingsView > renders 1`] = `
</div>
</div>
</div>
<div class="flex-container justify-center"><button data-v-24e38f3d="" class="button button--danger" data-test-id="reset-button"><svg data-v-24e38f3d="" viewBox="0 0 24 24" aria-hidden="true" style="width: 1.25rem; height: 1.25rem;">
<div data-v-bcc04aab="" class="flex-container flex-col min-h-0"><label data-v-bcc04aab="" class="uppercase text-xs">Common Questions</label>
<div data-v-bcc04aab="" class="flex-container flex-col has-scroll"><button data-v-bcc04aab="" id="headlessui-disclosure-button-v-6" type="button" aria-expanded="false" data-headlessui-state="" class="QA__button"><span data-v-bcc04aab="">What's this app for?</span><svg data-v-bcc04aab="" viewBox="0 0 24 24" aria-hidden="true" style="width: 1.25rem; height: 1.25rem;" class="">
<path d="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z" class="transition-all"></path>
</svg></button>
<transition-stub data-v-bcc04aab="" enteractiveclass="transition duration-100 ease-out" enterfromclass="transform h-0 opacity-0" entertoclass="transform h-full opacity-100" leaveactiveclass="transition duration-75 ease-out" leavefromclass="transform h-full opacity-100" leavetoclass="transform h-0 opacity-0" appear="false" persisted="false" css="true">
<!---->
</transition-stub><button data-v-bcc04aab="" id="headlessui-disclosure-button-v-8" type="button" aria-expanded="false" data-headlessui-state="" class="QA__button"><span data-v-bcc04aab="">What's the science?</span><svg data-v-bcc04aab="" viewBox="0 0 24 24" aria-hidden="true" style="width: 1.25rem; height: 1.25rem;" class="">
<path d="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z" class="transition-all"></path>
</svg></button>
<transition-stub data-v-bcc04aab="" enteractiveclass="transition duration-100 ease-out" enterfromclass="transform h-0 opacity-0" entertoclass="transform h-full opacity-100" leaveactiveclass="transition duration-75 ease-out" leavefromclass="transform h-full opacity-100" leavetoclass="transform h-0 opacity-0" appear="false" persisted="false" css="true">
<!---->
</transition-stub><button data-v-bcc04aab="" id="headlessui-disclosure-button-v-10" type="button" aria-expanded="false" data-headlessui-state="" class="QA__button"><span data-v-bcc04aab="">Is the app monetized?</span><svg data-v-bcc04aab="" viewBox="0 0 24 24" aria-hidden="true" style="width: 1.25rem; height: 1.25rem;" class="">
<path d="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z" class="transition-all"></path>
</svg></button>
<transition-stub data-v-bcc04aab="" enteractiveclass="transition duration-100 ease-out" enterfromclass="transform h-0 opacity-0" entertoclass="transform h-full opacity-100" leaveactiveclass="transition duration-75 ease-out" leavefromclass="transform h-full opacity-100" leavetoclass="transform h-0 opacity-0" appear="false" persisted="false" css="true">
<!---->
</transition-stub><button data-v-bcc04aab="" id="headlessui-disclosure-button-v-12" type="button" aria-expanded="false" data-headlessui-state="" class="QA__button"><span data-v-bcc04aab="">Is my data safe?</span><svg data-v-bcc04aab="" viewBox="0 0 24 24" aria-hidden="true" style="width: 1.25rem; height: 1.25rem;" class="">
<path d="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z" class="transition-all"></path>
</svg></button>
<transition-stub data-v-bcc04aab="" enteractiveclass="transition duration-100 ease-out" enterfromclass="transform h-0 opacity-0" entertoclass="transform h-full opacity-100" leaveactiveclass="transition duration-75 ease-out" leavefromclass="transform h-full opacity-100" leavetoclass="transform h-0 opacity-0" appear="false" persisted="false" css="true">
<!---->
</transition-stub><button data-v-bcc04aab="" id="headlessui-disclosure-button-v-14" type="button" aria-expanded="false" data-headlessui-state="" class="QA__button"><span data-v-bcc04aab="">How to get in touch?</span><svg data-v-bcc04aab="" viewBox="0 0 24 24" aria-hidden="true" style="width: 1.25rem; height: 1.25rem;" class="">
<path d="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z" class="transition-all"></path>
</svg></button>
<transition-stub data-v-bcc04aab="" enteractiveclass="transition duration-100 ease-out" enterfromclass="transform h-0 opacity-0" entertoclass="transform h-full opacity-100" leaveactiveclass="transition duration-75 ease-out" leavefromclass="transform h-full opacity-100" leavetoclass="transform h-0 opacity-0" appear="false" persisted="false" css="true">
<!---->
</transition-stub><button data-v-bcc04aab="" id="headlessui-disclosure-button-v-16" type="button" aria-expanded="false" data-headlessui-state="" class="QA__button"><span data-v-bcc04aab="">What counts as a portion?</span><svg data-v-bcc04aab="" viewBox="0 0 24 24" aria-hidden="true" style="width: 1.25rem; height: 1.25rem;" class="">
<path d="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z" class="transition-all"></path>
</svg></button>
<transition-stub data-v-bcc04aab="" enteractiveclass="transition duration-100 ease-out" enterfromclass="transform h-0 opacity-0" entertoclass="transform h-full opacity-100" leaveactiveclass="transition duration-75 ease-out" leavefromclass="transform h-full opacity-100" leavetoclass="transform h-0 opacity-0" appear="false" persisted="false" css="true">
<!---->
</transition-stub><button data-v-bcc04aab="" id="headlessui-disclosure-button-v-18" type="button" aria-expanded="false" data-headlessui-state="" class="QA__button"><span data-v-bcc04aab="">But strawberry is a...</span><svg data-v-bcc04aab="" viewBox="0 0 24 24" aria-hidden="true" style="width: 1.25rem; height: 1.25rem;" class="">
<path d="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z" class="transition-all"></path>
</svg></button>
<transition-stub data-v-bcc04aab="" enteractiveclass="transition duration-100 ease-out" enterfromclass="transform h-0 opacity-0" entertoclass="transform h-full opacity-100" leaveactiveclass="transition duration-75 ease-out" leavefromclass="transform h-full opacity-100" leavetoclass="transform h-0 opacity-0" appear="false" persisted="false" css="true">
<!---->
</transition-stub>
</div>
</div>
<div class="flex-container flex-col justify-center"><label for="reset-button" class="uppercase text-xs">Remove all data from the app</label><button data-v-24e38f3d="" class="button button--danger self-end" id="reset-button" data-test-id="reset-button"><svg data-v-24e38f3d="" viewBox="0 0 24 24" aria-hidden="true" style="width: 1.25rem; height: 1.25rem;">
<path d="M9,3V4H4V6H5V19A2,2 0 0,0 7,21H17A2,2 0 0,0 19,19V6H20V4H15V3H9M9,8H11V17H9V8M13,8H15V17H13V8Z" class="transition-all"></path>
</svg>Reset</button></div>"
`;
48 changes: 45 additions & 3 deletions src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,53 @@
"en": "English",
"fi": "Suomi"
},
"qa": {
"appPurpose": {
"title": "What's this app for?",
"text": "Eat Your Veggies is a free app for tracking plant-based ingredients on weekly basis in your diet. According to a study, consuming 30 or more veggies weekly has multiple health benefits over a less versatile diet. The key, according to study, is not as much in the amounts you consume, but in variation."
},
"categories": {
"title": "But strawberry is a...",
"text": "...false fruit, I know. Also tomato is not a vegetable in biological sense, so the app takes some liberties in its categories. Still, please report any major inaccuracies you come across! You can also request missing veggies to be added. They should be such that are commercially available globally."
},
"contact": {
"link": {
"url": "https://github.com/ajuvonen/veggies/",
"text": "GitHub"
},
"title": "How to get in touch?",
"text": "You can find the project page in {0}. The page has separate boards for reporting issues and engaging in other discussion. Thank you for your interest towards the project!"
},
"isItFree": {
"title": "Is the app monetized?",
"text": "The app is free to use, and it has no advertisements. There will be a possibility to donate, but don't feel obliged."
},
"isMyDataSafe": {
"title": "Is my data safe?",
"text": "The data is stored in your browser's local storage and is not shared with any third parties. You can at any time you wish reset the app using the button below."
},
"studyDetails": {
"link": {
"url": "https://doi.org/10.1128/msystems.00031-18",
"text": "American Society for Microbiology (ASM)"
},
"title": "What's the science?",
"text": "I'm neither a nutritian nor a biologist, so I don't want to make exaggerated claims or interpretations. I'm not affiliated with the study in any way, but if you want to read more about the study, look up The American Gut Project from the journal of {0}."
},
"title": "Common Questions",
"whatCounts": {
"title": "What counts as a portion?",
"text": "Ultimately, how you use the app is up to your discretion. However, consider that minuscule amounts might not be of any nutritional value. Therefore I personally consider only portions of a heaping tablespoon or larger adequate. It is also worth noting that very processed foods don't count towards a portion. So ketchup should not equal a tomato."
}
},
"settings": {
"locale": "Language",
"reset": "Reset",
"resetDialogText": "Continuing with the reset will wipe all your previously saved data and start from scratch. This action cannot be undone.",
"resetDialogTitle": "Are you sure you want to reset?",
"reset": {
"button": "Reset",
"label": "Remove all data from the app",
"text": "Continuing with the reset will wipe all your previously saved data and start from scratch. This action cannot be undone.",
"title": "Are you sure you want to reset?"
},
"title": "Settings"
},
"stats": {
Expand Down
48 changes: 45 additions & 3 deletions src/i18n/fi.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,53 @@
"en": "English",
"fi": "Suomi"
},
"qa": {
"appPurpose": {
"title": "Mitä sovelluksella tehdään",
"text": "Eat Your Veggies on ilmainen sovellus kasviperäisten ruoka-aineiden seuraamiseen ruokavaliossasi. Tutkimustulosten mukaan 30:n erilaisen kasviksen kuluttaminen viikoittain johtaa lukuisiin terveyshyötyihin vähemmän monipuoliseen ruokavalioon verrattuna. Avainasemassa ei siis tutkimuksen mukaan niinkään ole kulutettu määrä kuin monipuolisuus."
},
"categories": {
"title": "Mutta mansikkahan on..",
"text": "...epähedelmä, tiedän. Tomaattikaan ei ole biologisessa mielessä vihannes, joten sovelluksessa otetaan pieniä vapauksia kategorioiden suhteen. Ilmoita silti suuret epätarkkuudet joita löydät. Voit myös ehdottaa puuttuvia vihanneksia sovellukseen lisättäväksi. Niiden pitäisi olla sellaisia, joita on kaupallisesti saatavilla maailmanlaajuisesti."
},
"contact": {
"link": {
"url": "https://github.com/ajuvonen/veggies/",
"text": "GitHub"
},
"title": "Mihin voin ottaa yhteyttä?",
"text": "Projektin sivu on täällä: {0}. Sivulta löytyy erilliset osiot bugien raportointiin sekä yleiseen keskusteluun. Kiitos mielenkiinnosta projektia kohtaan!"
},
"isItFree": {
"title": "Maksaako sovelluksen käyttö?",
"text": "Sovellus on ilmainen eikä sisällä mainoksia. Mukaan on tulossa mahdollisuus tehdä lahjoitus, mutta se ei ole pakollista."
},
"isMyDataSafe": {
"title": "Ovatko tietoni turvassa?",
"text": "Tietoja säilytetään ainoastaan selaimesi paikallisessa tallennustilassa laitteellasi, eikä niitä jaeta kolmansille osapuolille. Voit milloin vain tyhjentää tietosi alla olevalla napilla."
},
"studyDetails": {
"link": {
"url": "https://doi.org/10.1128/msystems.00031-18",
"text": "American Society for Microbiology (ASM)"
},
"title": "Mihin sovellus perustuu?",
"text": "En ole ravitsemusterapeutti enkä biologi, joten haluan välttää liioiteltujen terveysväittämien tai tulkintojen esittämistä. En ole kytköksissä tutkimusta tehneeseen ryhmään millään tavalla, mutta mikäli haluat lukea siitä lisää, tutustu The American Gut Projectiin julkaisussa {0}."
},
"title": "Yleisiä kysymyksiä",
"whatCounts": {
"title": "Mikä lasketaan annokseksi?",
"text": "Se, miten sovellusta käytät, on viime kädessä kiinni omasta harkinnastasi. Huomioi kuitenkin, että hyvin vähäisissä määrissä kasviksia ei ole merkittävää ravitsemuksellista arvoa. Itse lasken mukaan vain kukkurallista ruokalusikkaa suuremmat annoskoot. Mainittakoon myös, että pitkälle prosessoiduilla ruoka-aineilla ei pidä korvata kasviksia. Ketsuppia ei siis lasketa tomaatiksi."
}
},
"settings": {
"locale": "Kieli",
"reset": "Tyhjennä",
"resetDialogText": "Tyhjennys poistaa kaikki sovellukseen tallennetut tiedot ja palauttaa sovelluksen alkutilaansa. Tätä toimenpidettä ei voi perua.",
"resetDialogTitle": "Haluatko tyhjentää sovelluksen?",
"reset": {
"button": "Tyhjennä",
"label": "Poista sovelluksen tiedot",
"text": "Tyhjennys poistaa kaikki sovellukseen tallennetut tiedot ja palauttaa sovelluksen alkutilaansa. Tätä toimenpidettä ei voi perua.",
"title": "Haluatko tyhjentää sovelluksen?"
},
"title": "Asetukset"
},
"stats": {
Expand Down
15 changes: 10 additions & 5 deletions src/views/SettingsView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {useActivityStore} from '@/stores/activityStore';
import {useAppStateStore} from '@/stores/appStateStore';
import LocaleChanger from '@/components/LocaleChanger.vue';
import ModalDialog from '@/components/ModalDialog.vue';
import QAComponent from '@/components/QAComponent.vue';
const router = useRouter();
Expand All @@ -22,18 +23,22 @@ const reset = () => {

<template>
<LocaleChanger />
<div class="flex-container justify-center">
<QAComponent />
<div class="flex-container flex-col justify-center">
<label for="reset-button" class="uppercase text-xs">{{ $t('settings.reset.label') }}</label>
<ButtonComponent
id="reset-button"
variant="danger"
icon="trashCan"
data-test-id="reset-button"
class="self-end"
@click="resetDialogOpen = true"
>{{ $t('settings.reset') }}</ButtonComponent
>{{ $t('settings.reset.button') }}</ButtonComponent
>
</div>
<ModalDialog v-model="resetDialogOpen" :title="$t('settings.resetDialogTitle')">
<ModalDialog v-model="resetDialogOpen" :title="$t('settings.reset.title')">
<template #content>
<p>{{ $t('settings.resetDialogText') }}</p>
<p>{{ $t('settings.reset.text') }}</p>
</template>
<template #buttons>
<ButtonComponent data-test-id="cancel-button" @click="resetDialogOpen = false">{{
Expand All @@ -44,7 +49,7 @@ const reset = () => {
variant="danger"
icon="trashCan"
@click="reset()"
>{{ $t('settings.reset') }}</ButtonComponent
>{{ $t('settings.reset.button') }}</ButtonComponent
>
</template>
</ModalDialog>
Expand Down

0 comments on commit 63ad181

Please sign in to comment.