Skip to content

Commit

Permalink
issue 54
Browse files Browse the repository at this point in the history
  • Loading branch information
jho44 committed Sep 19, 2023
1 parent ba0e0b1 commit 04e52ce
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 47 deletions.
3 changes: 3 additions & 0 deletions src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,6 @@ export type Row = {
endHr: number | undefined;
endMin: number | undefined;
};

export const LEGEND_STR =
'Legend: 🏠(host) 🚗(visit) 👤(dropoff) 👥(together) 🏫(via school) ⭐(good) 🌟(great) 🙏(needed)\n';
7 changes: 5 additions & 2 deletions src/lib/format.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { EMOTICONS_REVERSE, type Row } from '$lib/constants';
import { getObjectivePronoun } from './parse';

function getScheduleItem(row: Row): string {
let scheduleItem = '';
Expand Down Expand Up @@ -32,7 +31,7 @@ function updateLastScheduleItem(schedule: string[], newDate: string): void {
dates[dates.length - 1] = newDate;
schedule[schedule.length - 1] = dates.join('-');
} else {
schedule[schedule.length - 1] += `-${newDate}`;
schedule[schedule.length - 1] = `${schedule[schedule.length - 1].trim()}-${newDate}`;
}
}

Expand Down Expand Up @@ -118,3 +117,7 @@ export function circleInviteMsg(user: any, kidNames: string[], toPhone: string)
user.firstName
}`;
}

export function fullName(firstName: string, lastName: string | null) {
return `${firstName}${lastName ? ` ${lastName}` : ''}`;
}
141 changes: 140 additions & 1 deletion src/lib/server/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ import { error } from '@sveltejs/kit';

import { AvailabilityStatus, type Pronoun } from '@prisma/client';
import type { User } from '@prisma/client';
import { toLocalTimezone } from '../date';
import { dateTo12Hour, toLocalTimezone } from '../date';
import { dateNotes } from './sanitize';
import prisma from '$lib/prisma';
import { findHouseConnection } from './shared';
import { sendMsg } from './twilio';
import { DAYS } from '$lib/constants';
import { getAvailRangeParts } from '$lib/parse';
import { generateFullSchedule } from '$lib/format';

async function findHouseholdInvite(reqId: number) {
return await prisma.joinHouseholdRequest.findUnique({
Expand Down Expand Up @@ -699,7 +703,142 @@ async function removeHouseholdAdult(req: { id: number }, user: User) {
});
}

async function sendFaqLinks(
adults1: { phone: string }[],
adults2: { phone: string }[],
household1: { name: string; id: number },
household2: { name: string; id: number },
initiator: User
) {
// go through each number and send the FAQ links
return await Promise.all([
...adults1.map(async ({ phone }: { phone: string }) =>
sendMsg(
{
phone,
type: 'householdFaq',
otherHouseholdName: household2.name,
otherHouseholdId: household2.id
},
initiator
)
),
...adults2.map(async ({ phone }: { phone: string }) =>
sendMsg(
{
phone,
type: 'householdFaq',
otherHouseholdName: household1.name,
otherHouseholdId: household1.id
},
initiator
)
)
]);
}

async function getHouseholdsFullSched(householdId: number, user: { timeZone: string }) {
const now = new Date();
const startDate = new Date(`${now.getMonth() + 1}/${now.getDate()}`);
const endDate = new Date(startDate);
endDate.setDate(endDate.getDate() + 21);

const dates = await prisma.availabilityDate.findMany({
where: {
householdId,
date: {
gte: startDate,
lte: endDate
}
},
orderBy: [
{
date: 'asc'
}
]
});

const rows = dates.map((d) => {
const { date, status, startTime, endTime, notes, emoticons } = d;
const englishDay = DAYS[date.getDay()];
const monthDay = `${date.getMonth() + 1}/${date.getDate()}`;

let availRange;
let startHr;
let startMin;
let endHr;
let endMin;
let emoticonSet = new Set<string>(emoticons?.split(','));
if (status === AvailabilityStatus.AVAILABLE) {
availRange = 'Available';
if (startTime && endTime)
availRange = `${dateTo12Hour(toLocalTimezone(startTime, user.timeZone))}-${dateTo12Hour(
toLocalTimezone(endTime, user.timeZone)
)}`;
const timeParts = getAvailRangeParts(availRange);
startHr = timeParts.startHr;
startMin = timeParts.startMin;
endHr = timeParts.endHr;
endMin = timeParts.endMin;
} else if (status === AvailabilityStatus.BUSY) {
availRange = 'Busy';
}

return {
englishDay,
monthDay,
availRange,
notes: notes ?? undefined,
emoticons: emoticonSet,
startHr,
startMin,
endHr,
endMin
};
});

return generateFullSchedule(rows);
}

async function sendSched(
adults1: { phone: string; timeZone: string }[],
adults2: { phone: string; timeZone: string }[],
household1: { name: string; id: number },
household2: { name: string; id: number },
initiator: User
) {
// go through each number and send sched
return await Promise.all([
...adults1.map(async (recipient: { phone: string; timeZone: string }) => {
const sched = await getHouseholdsFullSched(household2.id, recipient);
return await sendMsg(
{
phone: recipient.phone,
type: 'newFriendNotif',
sched: sched.join('\n'),
otherHouseholdName: household2.name
},
initiator
);
}),
...adults2.map(async (recipient: { phone: string; timeZone: string }) => {
const sched = await getHouseholdsFullSched(household1.id, recipient);
return await sendMsg(
{
phone: recipient.phone,
type: 'newFriendNotif',
sched: sched.join('\n'),
otherHouseholdName: household1.name
},
initiator
);
})
]);
}

export {
sendSched,
sendFaqLinks,
deleteHouseholdInvite,
acceptHouseholdInvite,
createCircleInvite,
Expand Down
13 changes: 9 additions & 4 deletions src/lib/server/sanitize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import type { User } from '@prisma/client';
import { error } from '@sveltejs/kit';
import prisma from '$lib/prisma';
import sanitizerFunc from 'sanitize';
import { fullName } from '$lib/format';
import { LEGEND_STR } from '$lib/constants';

const sanitizer = sanitizerFunc();

Expand Down Expand Up @@ -35,11 +37,14 @@ export const circleNotif = async (sched: string, user: User, diff: boolean) => {
.map((kid) => `${kid.firstName}${kid.lastName ? ` ${kid.lastName}` : ''}`)
.join(', ');

return `${user.firstName}${
user.lastName && user.lastName.length ? ` ${user.lastName}` : ''
} (parent of ${kidNames}) has ${
return `${fullName(user.firstName, user.lastName)} (parent of ${kidNames}) has ${
diff ? 'changed the following days on' : 'updated'
} ${objectivePronoun} tentative schedule:\nLegend: 🏠(host) 🚗(visit) 👤(dropoff) 👥(together) 🏫(via school) ⭐(good) 🌟(great) 🙏(needed)\n\n${sanitizedSched}`;
} ${objectivePronoun} tentative schedule:\n${LEGEND_STR}\n${sanitizedSched}`;
};

export const newFriendNotif = async (sched: string, otherHouseholdName: string) => {
const sanitizedSched = sanitize(sched);
return `The tentative schedule of ${otherHouseholdName} is:\n${LEGEND_STR}\n${sanitizedSched}`;
};

export const dateNotes = (notes: string) => sanitize(notes);
12 changes: 7 additions & 5 deletions src/lib/server/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,19 @@ export async function findHouseConnection(hId1: number, hId2: number) {
};
}

export async function getPhoneNumsInHousehold(id: number | null) {
export async function getUserAttrsInHousehold(id: number | null, attrs: string[]) {
if (!id) return [];
const select: { [key: string]: true } = {};
attrs.forEach((attr) => {
select[attr] = true;
});
const users = await prisma.user.findMany({
where: {
householdId: id
},
select: {
phone: true
}
select
});
return users.map((u) => u.phone);
return users;
}

export async function getHousehold(id: number | null, attrs: string[]) {
Expand Down
10 changes: 8 additions & 2 deletions src/lib/server/twilio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { env as public_env } from '$env/dynamic/public';
import { error, json } from '@sveltejs/kit';
import Twilio from 'twilio';
import type { User } from '@prisma/client';
import { circleNotif } from './sanitize';
import { circleNotif, newFriendNotif } from './sanitize';
import { generate, save } from './login';
import { toLocalTimezone } from '../date';
import { DateTime } from 'luxon';
Expand All @@ -20,10 +20,16 @@ const msgToSend = async (
const url = public_env.PUBLIC_URL;
let msg;
switch (type) {
case 'householdFaq':
case 'newFriendNotif': {
const { sched, otherHouseholdName } = msgComps;
msg = await newFriendNotif(sched, otherHouseholdName);
break;
}
case 'householdFaq': {
const { otherHouseholdName, otherHouseholdId } = msgComps;
msg = `Your household and ${otherHouseholdName} are now connected. Please check out their FAQ here: ${url}/household/${otherHouseholdId}`;
break;
}
case 'login': {
const { phone, token, timeZone } = msgComps;
const magicLink = await prisma.magicLink
Expand Down
45 changes: 12 additions & 33 deletions src/routes/db/+server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ import {
deleteHouseholdInvite,
deleteKid,
deleteHousehold,
removeHouseholdAdult
removeHouseholdAdult,
sendFaqLinks,
sendSched
} from '$lib/server/db';
import { getHousehold, getPhoneNumsInHousehold, getProfileFromSession } from '$lib/server/shared';
import { sendMsg } from '$lib/server/twilio';
import { getHousehold, getProfileFromSession, getUserAttrsInHousehold } from '$lib/server/shared';

export async function POST({
request,
Expand Down Expand Up @@ -60,14 +61,15 @@ export async function POST({
// get each household's id
const otherHouseholdId = await acceptFriendReq(req, user);

// get users' phones in both households
const [phones1, phones2] = await Promise.all([
await getPhoneNumsInHousehold(otherHouseholdId),
await getPhoneNumsInHousehold(user.householdId)
// get users' phones, time zones in both households
const userAttrs = ['phone', 'timeZone'];
const [adults1, adults2] = await Promise.all([
await getUserAttrsInHousehold(otherHouseholdId, userAttrs),
await getUserAttrsInHousehold(user.householdId, userAttrs)
]);

// get names for both households
const attrs = ['name'];
const attrs = ['name', 'id'];
const household1 = await getHousehold(otherHouseholdId, attrs);
if (!household1) {
throw error(404, {
Expand All @@ -81,31 +83,8 @@ export async function POST({
});
}

// go through each number and send the FAQ links
await Promise.all([
...phones1.map(async (phone: string) =>
sendMsg(
{
phone,
type: 'householdFaq',
otherHouseholdName: household2.name,
otherHouseholdId: user.householdId
},
user
)
),
...phones2.map(async (phone: string) =>
sendMsg(
{
phone,
type: 'householdFaq',
otherHouseholdName: household1.name,
otherHouseholdId: otherHouseholdId
},
user
)
)
]);
await sendFaqLinks(adults1, adults2, household1, household2, user);
await sendSched(adults1, adults2, household1, household2, user);
} else if (req.type === 'rejectFriendReq') {
await deleteFriendReq(req, user);
} else if (req.type === 'deleteFriend') {
Expand Down

0 comments on commit 04e52ce

Please sign in to comment.