Mari's guided journal software.
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.
 
 

196 lines
7.6 KiB

import {
DateQuestion,
EditorQuestion,
ListQuestion,
NumberQuestion,
} from "inquirer";
import {Separator} from "../Inquire.js";
import {InquireFunction} from "../Inquire.js";
import {SleepQuality, SleepRecord, sleepRecordToString, WakeQuality} from "../../datatypes/SleepRecord.js";
import {DateTime} from "luxon";
import chalk from "chalk";
import {EntryMainMenuChoice, makeEntryMainMenuChoice} from "./EntryMainMenuPrompt.js";
export interface SleepRecordPromptOptions extends Partial<Omit<EditorQuestion, "name"|"type"|"default"> & Omit<DateQuestion, "name"|"type"|"default"> & Omit<ListQuestion, "name"|"type"|"default"> & Omit<NumberQuestion, "name"|"type"|"default">>{
default?: SleepRecord,
}
export interface SleepRecordPromptDependencies {
readonly inquire: InquireFunction<EditorQuestion, string> & InquireFunction<DateQuestion, Date|null> & InquireFunction<ListQuestion & {default: SleepQuality|undefined}, SleepQuality|undefined> & InquireFunction<ListQuestion & {default: WakeQuality|undefined}, WakeQuality|undefined> & InquireFunction<NumberQuestion, number>
}
export function sleepRecordPrompt(deps: SleepRecordPromptDependencies): {
(options: SleepRecordPromptOptions): Promise<SleepRecord|null>,
mainMenu: EntryMainMenuChoice<"sleepRecords">,
} {
return makeEntryMainMenuChoice({
property: "sleepRecords",
name: (input) => typeof input !== "object" || input.length === 0 ? `Add sleep record` : `Change sleep record ${chalk.dim(`(currently ${chalk.greenBright(sleepRecordToString(input[0]))})`)}`,
key: "z",
injected: (options) => promptForSleepRecord(options, deps),
toOptions: (value) => typeof value !== "object" || value.length === 0 ? {} : {default: value[0]},
toProperty: (value) => value === null ? undefined : [value],
})
}
export async function promptForSleepRecord(options: SleepRecordPromptOptions, {inquire}: SleepRecordPromptDependencies): Promise<SleepRecord | null> {
const oldBedTime = options.default?.sleepAt
const newBedTime = await inquire({
...options,
type: "date",
message: "About when did you get to sleep?",
clearable: true,
startCleared: false,
default: oldBedTime ?? DateTime.local().set({hour: 23, minute: 0, second: 0, millisecond: 0}).minus({days: 1}).toJSDate(),
format: {
year: undefined,
weekday: "short",
month: "short",
day: "numeric",
hour: "numeric",
minute: "numeric",
second: undefined,
fractionalSecondDigits: undefined,
timeZoneName: "short",
},
startingDatePart: "hour",
deltas: {
weekday: 1,
hour: [1, 5, 10],
minute: [15, 5, 1],
default: 0
}
})
const oldSleepQuality = options.default?.sleepQuality
const newSleepQuality = await inquire({
...options,
type: "list",
message: `How'd you sleep?`,
choices: [
{
value: SleepQuality.ACIDIC,
name: `Acidic ${chalk.dim("(extremely poor/extremely restless/heavy acid reflux)")}`
},
{
value: SleepQuality.RESTLESS,
name: `Restless ${chalk.dim("(very poor/very restless/fever dreamy)")}`
},
{
value: SleepQuality.NIGHTMARISH,
name: `Nightmarish ${chalk.dim("(poor/restless/plagued with nightmares)")}`
},
{
value: SleepQuality.TIMESKIP,
name: `Timeskip ${chalk.dim("(neutral/passage of time not recognized)")}`
},
{
value: SleepQuality.DREAMLESS,
name: `Dreamless ${chalk.dim("(good/peaceful/no dreams had or remembered)")}`
},
{
value: SleepQuality.DREAMY,
name: `Dreamy ${chalk.dim("(very good/peaceful/neutral to somewhat pleasant dreams)")}`
},
{
value: SleepQuality.ECSTASY,
name: `Ecstasy ${chalk.dim("(extremely good/very peaceful/very pleasant dreams)")}`
},
new Separator(),
{
value: undefined,
name: `Uncertain`
},
],
default: oldSleepQuality ?? SleepQuality.TIMESKIP,
pageSize: 999,
})
const oldInterruptions = options.default?.interruptions
const newInterruptionsRaw = await inquire({
...options,
type: "number",
message: "How many times did you end up waking up during the sleep?",
default: oldInterruptions ?? -1,
})
const newInterruptions = newInterruptionsRaw < 0 ? undefined : Math.round(newInterruptionsRaw)
const oldWakeTime = options.default?.wakeAt
const newWakeTime = await inquire({
...options,
type: "date",
message: "Around when did you get up?",
clearable: true,
startCleared: false,
default: oldWakeTime ?? DateTime.local().set({hour: 7, minute: 0, second: 0, millisecond: 0}).toJSDate(),
format: {
year: undefined,
weekday: "short",
month: "short",
day: "numeric",
hour: "numeric",
minute: "numeric",
second: undefined,
fractionalSecondDigits: undefined,
timeZoneName: "short",
},
startingDatePart: "hour",
deltas: {
hour: [1, 5, 10],
minute: [15, 5, 1],
default: 0
}
})
const oldWakeQuality = options.default?.wakeQuality
const newWakeQuality = await inquire({
...options,
type: "list",
message: `How'd you feel when you got up?`,
choices: [
{
value: WakeQuality.AGONIZED,
name: `Agonized ${chalk.dim("(in physical pain/barely able or unable to get out of bed)")}`
},
{
value: WakeQuality.EXHAUSTED,
name: `Exhausted ${chalk.dim("(very tired/not wanting to get out of bed)")}`
},
{
value: WakeQuality.DROWSY,
name: `Drowsy ${chalk.dim("(a bit sleepy but willing to get out of bed)")}`
},
{
value: WakeQuality.RESTED,
name: `Rested ${chalk.dim("(well rested and ready to get going)")}`
},
{
value: WakeQuality.ENERGIZED,
name: `Energized ${chalk.dim("(thoroughly recharged and eager to get up and running)")}`
},
new Separator(),
{
value: undefined,
name: `Uncertain`
},
],
default: oldWakeQuality ?? WakeQuality.DROWSY,
pageSize: 999,
})
const oldDreamJournal = options.default?.dreams
const newDreamJournalRaw = (await inquire({
...options,
type: "editor",
message: typeof oldDreamJournal === "string" ? `Edit dream journal for this sleep session:` : `Type up dream journal for this sleep session:`,
default: oldDreamJournal,
})).trimEnd()
const newDreamJournal = newDreamJournalRaw === "" ? undefined : newDreamJournalRaw
const result: SleepRecord = {
dreams: newDreamJournal,
interruptions: newInterruptions,
sleepAt: newBedTime ?? undefined,
sleepQuality: newSleepQuality,
wakeAt: newWakeTime ?? undefined,
wakeQuality: newWakeQuality,
}
return (
Object.keys(result).map((key: keyof SleepRecord) => result[key]).some(value => (value !== undefined))
? result
: null)
}