Trent Larson
9 months ago
5 changed files with 241 additions and 4 deletions
@ -0,0 +1,214 @@ |
|||||
|
<template> |
||||
|
<div v-if="visible" class="dialog-overlay"> |
||||
|
<div class="dialog"> |
||||
|
<h1 class="text-xl font-bold text-center mb-4">Here's one:</h1> |
||||
|
<span class="flex justify-between h-24"> |
||||
|
<span |
||||
|
class="rounded-l border border-slate-400 bg-slate-200 h-full px-4 py-2 flex h-screen" |
||||
|
@click="prevIdea()" |
||||
|
> |
||||
|
<fa icon="chevron-left" class="m-auto" /> |
||||
|
</span> |
||||
|
|
||||
|
<div class="m-2"> |
||||
|
<span v-if="currentIdeaIndex < IDEAS.length"> |
||||
|
<p class="text-center text-lg font-bold"> |
||||
|
{{ IDEAS[currentIdeaIndex] }} |
||||
|
</p> |
||||
|
</span> |
||||
|
<div v-if="currentIdeaIndex == IDEAS.length + 0"> |
||||
|
<p class="text-center text-lg font-bold"> |
||||
|
Did this person or someone near them do something – maybe a |
||||
|
while ago? |
||||
|
<br /> |
||||
|
<span v-if="currentContact?.name == null" class="text-orange-500"> |
||||
|
That's all your contacts. |
||||
|
</span> |
||||
|
<span v-else>{{ |
||||
|
currentContact.name || AppString.NO_CONTACT_NAME |
||||
|
}}</span> |
||||
|
</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<span |
||||
|
class="rounded-r border border-slate-400 bg-slate-200 h-full px-4 py-2 flex h-screen" |
||||
|
@click="nextIdea()" |
||||
|
> |
||||
|
<fa icon="chevron-right" class="m-auto" /> |
||||
|
</span> |
||||
|
</span> |
||||
|
<button |
||||
|
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mt-4" |
||||
|
@click="cancel" |
||||
|
> |
||||
|
That's it. |
||||
|
</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts"> |
||||
|
import { Vue, Component } from "vue-facing-decorator"; |
||||
|
|
||||
|
import { AppString } from "@/constants/app"; |
||||
|
import { db } from "@/db/index"; |
||||
|
import { Contact } from "@/db/tables/contacts"; |
||||
|
|
||||
|
interface Notification { |
||||
|
group: string; |
||||
|
type: string; |
||||
|
title: string; |
||||
|
text: string; |
||||
|
} |
||||
|
|
||||
|
@Component |
||||
|
export default class GivenPrompts extends Vue { |
||||
|
$notify!: (notification: Notification, timeout?: number) => void; |
||||
|
|
||||
|
IDEAS = [ |
||||
|
"Did anyone fix food for you?", |
||||
|
"Did a family member do something for you?", |
||||
|
"Did anyone give you a compliment?", |
||||
|
"Did you see anyone give to someone else?", |
||||
|
"Did anyone give you a good laugh?", |
||||
|
"Do you recall anything that was given to you while you were young?", |
||||
|
"Do you know of a way an ancestor contributed to your life?", |
||||
|
]; |
||||
|
OTHER_PROMPTS = 1; |
||||
|
CONTACT_PROMPT_INDEX = this.IDEAS.length; // expected after other prompts |
||||
|
|
||||
|
currentContact: Contact | undefined = undefined; |
||||
|
currentIdeaIndex = 0; |
||||
|
numContacts = 0; |
||||
|
shownContactDbIndices: number[] = []; |
||||
|
visible = false; |
||||
|
|
||||
|
AppString = AppString; |
||||
|
|
||||
|
async open() { |
||||
|
this.visible = true; |
||||
|
|
||||
|
await db.open(); |
||||
|
this.numContacts = await db.contacts.count(); |
||||
|
} |
||||
|
|
||||
|
close() { |
||||
|
// close the dialog but don't change values (just in case some actions are added later) |
||||
|
this.visible = false; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get the next idea. |
||||
|
* If it is a contact prompt, loop through. |
||||
|
*/ |
||||
|
async nextIdea() { |
||||
|
// if we're incrementing to the contact prompt |
||||
|
// or if we're at the contact prompt and there was a previous contact... |
||||
|
if ( |
||||
|
this.currentIdeaIndex == this.CONTACT_PROMPT_INDEX - 1 || |
||||
|
(this.currentIdeaIndex == this.CONTACT_PROMPT_INDEX && |
||||
|
this.currentContact) |
||||
|
) { |
||||
|
this.currentIdeaIndex = this.CONTACT_PROMPT_INDEX; |
||||
|
this.findNextUnshownContact(); |
||||
|
} else { |
||||
|
// we're not at the contact prompt (or we ran out), so increment the idea index |
||||
|
this.currentIdeaIndex = |
||||
|
(this.currentIdeaIndex + 1) % (this.IDEAS.length + this.OTHER_PROMPTS); |
||||
|
// ... and clear out any other prompt info |
||||
|
this.currentContact = undefined; |
||||
|
this.shownContactDbIndices = []; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
prevIdea() { |
||||
|
if ( |
||||
|
this.currentIdeaIndex == |
||||
|
(this.CONTACT_PROMPT_INDEX + 1) % |
||||
|
(this.IDEAS.length + this.OTHER_PROMPTS) || |
||||
|
(this.currentIdeaIndex == this.CONTACT_PROMPT_INDEX && |
||||
|
this.currentContact) |
||||
|
) { |
||||
|
this.currentIdeaIndex = this.CONTACT_PROMPT_INDEX; |
||||
|
this.findNextUnshownContact(); |
||||
|
} else { |
||||
|
// we're not at the contact prompt (or we ran out), so increment the idea index |
||||
|
this.currentIdeaIndex--; |
||||
|
if (this.currentIdeaIndex < 0) { |
||||
|
this.currentIdeaIndex = this.IDEAS.length - 1 + this.OTHER_PROMPTS; |
||||
|
} |
||||
|
// ... and clear out any other prompt info |
||||
|
this.currentContact = undefined; |
||||
|
this.shownContactDbIndices = []; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async findNextUnshownContact() { |
||||
|
// get a random contact |
||||
|
if (this.shownContactDbIndices.length === this.numContacts) { |
||||
|
// no more contacts to show |
||||
|
this.currentContact = undefined; |
||||
|
} else { |
||||
|
// get a random contact that hasn't been shown yet |
||||
|
let someContactDbIndex = Math.floor(Math.random() * this.numContacts); |
||||
|
// and guarantee that one is found by walking past shown contacts |
||||
|
let shownContactIndex = |
||||
|
this.shownContactDbIndices.indexOf(someContactDbIndex); |
||||
|
while (shownContactIndex !== -1) { |
||||
|
// increment both indices until we find a spot where "shown" skips a spot |
||||
|
shownContactIndex = (shownContactIndex + 1) % this.numContacts; |
||||
|
someContactDbIndex = (someContactDbIndex + 1) % this.numContacts; |
||||
|
if ( |
||||
|
this.shownContactDbIndices[shownContactIndex] !== someContactDbIndex |
||||
|
) { |
||||
|
// we found a contact that hasn't been shown yet |
||||
|
break; |
||||
|
} |
||||
|
// continue |
||||
|
// ... and there must be at least one because shownContactDbIndices length < numContacts |
||||
|
} |
||||
|
this.shownContactDbIndices.push(someContactDbIndex); |
||||
|
this.shownContactDbIndices.sort(); |
||||
|
|
||||
|
// get the contact at that offset |
||||
|
await db.open(); |
||||
|
this.currentContact = await db.contacts |
||||
|
.offset(someContactDbIndex) |
||||
|
.first(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
cancel() { |
||||
|
this.currentContact = undefined; |
||||
|
this.currentIdeaIndex = 0; |
||||
|
this.numContacts = 0; |
||||
|
this.shownContactDbIndices = []; |
||||
|
|
||||
|
this.close(); |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
.dialog-overlay { |
||||
|
position: fixed; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
background-color: rgba(0, 0, 0, 0.5); |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
padding: 1.5rem; |
||||
|
} |
||||
|
|
||||
|
.dialog { |
||||
|
background-color: white; |
||||
|
padding: 1rem; |
||||
|
border-radius: 0.5rem; |
||||
|
width: 100%; |
||||
|
max-width: 500px; |
||||
|
} |
||||
|
</style> |
Loading…
Reference in new issue