You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

263 lines
9.3 KiB

<template>
<div v-if="visible" class="dialog-overlay">
<div class="dialog">
<h1 class="text-xl font-bold text-center relative">
Here's one:
<div
class="text-lg text-center p-2 leading-none absolute right-0 -top-1"
@click="cancel"
>
<font-awesome icon="xmark" class="w-[1em]"></font-awesome>
</div>
</h1>
<span class="mt-2 flex justify-between">
<span
v-if="currentCategory === CATEGORY_IDEAS"
class="rounded-l border border-slate-400 bg-slate-200 px-4 py-2 flex"
@click="prevIdea()"
>
<font-awesome icon="chevron-left" class="m-auto" />
</span>
<div class="m-2">
<span v-if="currentCategory === CATEGORY_IDEAS">
<p class="text-center text-lg">
{{ IDEAS[currentIdeaIndex] }}
</p>
</span>
<div v-if="currentCategory === CATEGORY_CONTACTS">
<p class="text-center">
<span
v-if="currentContact == null"
class="text-orange-500 text-lg"
>
That's all your contacts.
</span>
<span v-else>
<span class="text-lg">
Did {{ currentContact.name || AppString.NO_CONTACT_NAME }}
<br />
or someone near them do anything &ndash; maybe a while ago?
</span>
<span class="flex justify-between">
<span />
<button
class="text-center bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md mt-4"
@click="nextIdeaPastContacts()"
>
Skip Contacts <font-awesome icon="forward" />
</button>
</span>
</span>
</p>
</div>
</div>
<span
class="rounded-r border border-slate-400 bg-slate-200 px-4 py-2 flex"
@click="nextIdea()"
>
<font-awesome icon="chevron-right" class="m-auto" />
</span>
</span>
<button
class="block w-full text-center text-md uppercase bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md mt-4"
@click="proceed"
>
That's it!
</button>
</div>
</div>
</template>
<script lang="ts">
import { Vue, Component } from "vue-facing-decorator";
import { Router } from "vue-router";
import { AppString, NotificationIface } from "../constants/app";
import { db } from "../db/index";
import { Contact } from "../db/tables/contacts";
import { GiverReceiverInputInfo } from "../libs/util";
@Component
export default class GivenPrompts extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
CATEGORY_CONTACTS = 1;
CATEGORY_IDEAS = 0;
IDEAS = [
"What food did someone make? (How did it free up your time for something? Was something doable because it eased your stress?)",
"What did a family member do? (How did you take better action because it made you feel loved?)",
"What compliment did someone give you? (What task could you tackle because it boosted your confidence?)",
"Who is someone you can always rely on, and how did they demonstrate that? (What project tasks were enabled because you could depend on them?)",
"What did you see someone give to someone else? (What is the effect of the positivity you gained from seeing that?)",
"What is a way that someone helped you even though you have never met? (What different action did you take due to that newfound perspective or inspiration?)",
"How did a musician or author or artist inspire you? (What were you motivated to do more creatively because of that?)",
"What inspiration did you get from someone who handled tragedy well? (What could you accomplish with better grace or resilience after seeing their example?)",
"What is something worth respect that an organization gave you? (How did their contribution improve the situation or enable new activities?)",
"Who last gave you a good laugh? (What kind of bond or revitalization did that bring to a situation?)",
"What do you recall someone giving you while you were young? (How did it bring excitement or teach a skill or ignite a passion that resulted in improvements in your life?)",
"Who forgave you or overlooked a mistake? (How did that free you or build trust that enabled better relationships?)",
"What is a way an ancestor contributed to your life? (What in your life is now possible because of their efforts? What challenges are you undertaking knowing of their lives?)",
"What kind of help did someone at work give you? (How did that help with team progress? How did that lift your professional growth?)",
"How did a teacher or mentor or great example help you? (How did their guidance enhance your attitude or actions?)",
"What is a surprise gift you received? (What extra possibilities did it give you?)",
];
callbackOnFullGiftInfo?: (
contactInfo?: GiverReceiverInputInfo,
description?: string,
) => void;
currentCategory = this.CATEGORY_IDEAS; // 0 = IDEAS, 1 = CONTACTS
currentContact: Contact | undefined = undefined;
currentIdeaIndex = 0;
numContacts = 0;
shownContactDbIndices: Array<boolean> = [];
visible = false;
AppString = AppString;
async open(
callbackOnFullGiftInfo?: (
contactInfo?: GiverReceiverInputInfo,
description?: string,
) => void,
) {
this.visible = true;
this.callbackOnFullGiftInfo = callbackOnFullGiftInfo;
await db.open();
this.numContacts = await db.contacts.count();
this.shownContactDbIndices = new Array<boolean>(this.numContacts); // all undefined to start
}
cancel() {
this.currentCategory = this.CATEGORY_IDEAS;
this.currentContact = undefined;
this.currentIdeaIndex = 0;
this.numContacts = 0;
this.shownContactDbIndices = [];
this.visible = false;
}
proceed() {
// proceed with logic but don't change values (just in case some actions are added later)
this.visible = false;
if (this.currentCategory === this.CATEGORY_IDEAS) {
(this.$router as Router).push({
name: "contact-gift",
query: {
prompt: this.IDEAS[this.currentIdeaIndex],
},
});
} else {
// must be this.CATEGORY_CONTACTS
this.callbackOnFullGiftInfo?.(
this.currentContact as GiverReceiverInputInfo,
);
}
}
/**
* Get the next idea.
* If it is a contact prompt, loop through.
*/
async nextIdea() {
// check if the next one is an idea or a contact
if (this.currentCategory === this.CATEGORY_IDEAS) {
this.currentIdeaIndex++;
if (this.currentIdeaIndex === this.IDEAS.length) {
// must have just finished ideas so move to contacts
this.findNextUnshownContact();
}
} else {
// must be this.CATEGORY_CONTACTS
this.findNextUnshownContact();
// when that's finished, it'll reset to ideas
}
}
/**
* Get the previous idea.
* If it is a contact prompt, loop through.
*/
async prevIdea() {
// check if the next one is an idea or a contact
if (this.currentCategory === this.CATEGORY_IDEAS) {
this.currentIdeaIndex--;
if (this.currentIdeaIndex < 0) {
// must have just finished ideas so move to contacts
this.findNextUnshownContact();
}
} else {
// must be this.CATEGORY_CONTACTS
this.findNextUnshownContact();
// when that's finished, it'll reset to ideas
}
}
nextIdeaPastContacts() {
this.currentContact = undefined;
this.shownContactDbIndices = new Array<boolean>(this.numContacts);
this.currentCategory = this.CATEGORY_IDEAS;
// look at the previous idea and switch to the other side of the list
this.currentIdeaIndex =
this.currentIdeaIndex >= this.IDEAS.length ? 0 : this.IDEAS.length - 1;
}
async findNextUnshownContact() {
if (this.currentCategory === this.CATEGORY_IDEAS) {
// we're not in the contact prompts, so reset index array
this.shownContactDbIndices = new Array<boolean>(this.numContacts);
}
this.currentCategory = this.CATEGORY_CONTACTS;
let someContactDbIndex = Math.floor(Math.random() * this.numContacts);
let count = 0;
// as long as the index has an entry, loop
while (
this.shownContactDbIndices[someContactDbIndex] != null &&
count++ < this.numContacts
) {
someContactDbIndex = (someContactDbIndex + 1) % this.numContacts;
}
if (count >= this.numContacts) {
// all contacts have been shown
this.nextIdeaPastContacts();
} else {
// get the contact at that offset
await db.open();
this.currentContact = await db.contacts
.offset(someContactDbIndex)
.first();
this.shownContactDbIndices[someContactDbIndex] = true;
}
}
}
</script>
<style>
.dialog-overlay {
z-index: 50;
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>