remove current phone number from session
This commit is contained in:
parent
3ddd0d73ea
commit
836b1d8d1b
@ -12,7 +12,10 @@ export type KeypadLoaderData = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const loader: LoaderFunction = async ({ request }) => {
|
const loader: LoaderFunction = async ({ request }) => {
|
||||||
const { phoneNumber } = await requireLoggedIn(request);
|
const { twilio } = await requireLoggedIn(request);
|
||||||
|
const phoneNumber = await db.phoneNumber.findUnique({
|
||||||
|
where: { twilioAccountSid_isCurrent: { twilioAccountSid: twilio?.accountSid ?? "", isCurrent: true } },
|
||||||
|
});
|
||||||
const hasOngoingSubscription = true; // TODO
|
const hasOngoingSubscription = true; // TODO
|
||||||
const hasPhoneNumber = Boolean(phoneNumber);
|
const hasPhoneNumber = Boolean(phoneNumber);
|
||||||
const lastCall =
|
const lastCall =
|
||||||
|
@ -8,12 +8,17 @@ import getTwilioClient, { translateMessageDirection, translateMessageStatus } fr
|
|||||||
export type NewMessageActionData = {};
|
export type NewMessageActionData = {};
|
||||||
|
|
||||||
const action: ActionFunction = async ({ params, request }) => {
|
const action: ActionFunction = async ({ params, request }) => {
|
||||||
const { phoneNumber, twilio } = await requireLoggedIn(request);
|
const { twilio } = await requireLoggedIn(request);
|
||||||
if (!twilio) {
|
if (!twilio) {
|
||||||
throw new Error("unreachable");
|
throw new Error("unreachable");
|
||||||
}
|
}
|
||||||
const twilioAccount = await db.twilioAccount.findUnique({ where: { accountSid: twilio.accountSid } });
|
const [phoneNumber, twilioAccount] = await Promise.all([
|
||||||
if (!twilioAccount) {
|
db.phoneNumber.findUnique({
|
||||||
|
where: { twilioAccountSid_isCurrent: { twilioAccountSid: twilio.accountSid ?? "", isCurrent: true } },
|
||||||
|
}),
|
||||||
|
db.twilioAccount.findUnique({ where: { accountSid: twilio.accountSid } }),
|
||||||
|
]);
|
||||||
|
if (!phoneNumber || !twilioAccount) {
|
||||||
throw new Error("unreachable");
|
throw new Error("unreachable");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,11 +29,11 @@ const action: ActionFunction = async ({ params, request }) => {
|
|||||||
const message = await twilioClient.messages.create({
|
const message = await twilioClient.messages.create({
|
||||||
body: formData.content.toString(),
|
body: formData.content.toString(),
|
||||||
to: recipient,
|
to: recipient,
|
||||||
from: phoneNumber!.number,
|
from: phoneNumber.number,
|
||||||
});
|
});
|
||||||
await db.message.create({
|
await db.message.create({
|
||||||
data: {
|
data: {
|
||||||
phoneNumberId: phoneNumber!.id,
|
phoneNumberId: phoneNumber.id,
|
||||||
id: message.sid,
|
id: message.sid,
|
||||||
to: message.to,
|
to: message.to,
|
||||||
recipient: message.to,
|
recipient: message.to,
|
||||||
|
@ -7,13 +7,11 @@ import { Direction } from "@prisma/client";
|
|||||||
import NewMessageArea from "./new-message-area";
|
import NewMessageArea from "./new-message-area";
|
||||||
import { formatDate, formatTime } from "~/features/core/helpers/date-formatter";
|
import { formatDate, formatTime } from "~/features/core/helpers/date-formatter";
|
||||||
import { type ConversationLoaderData } from "~/features/messages/loaders/messages.$recipient";
|
import { type ConversationLoaderData } from "~/features/messages/loaders/messages.$recipient";
|
||||||
import useSession from "~/features/core/hooks/use-session";
|
|
||||||
|
|
||||||
export default function Conversation() {
|
export default function Conversation() {
|
||||||
const { phoneNumber } = useSession();
|
|
||||||
const params = useParams<{ recipient: string }>();
|
const params = useParams<{ recipient: string }>();
|
||||||
const recipient = decodeURIComponent(params.recipient ?? "");
|
const recipient = decodeURIComponent(params.recipient ?? "");
|
||||||
const { conversation } = useLoaderData<ConversationLoaderData>();
|
const { conversation, currentPhoneNumber } = useLoaderData<ConversationLoaderData>();
|
||||||
const transition = useTransition();
|
const transition = useTransition();
|
||||||
const messagesListRef = useRef<HTMLUListElement>(null);
|
const messagesListRef = useRef<HTMLUListElement>(null);
|
||||||
|
|
||||||
@ -21,8 +19,8 @@ export default function Conversation() {
|
|||||||
if (transition.submission) {
|
if (transition.submission) {
|
||||||
messages.push({
|
messages.push({
|
||||||
id: "temp",
|
id: "temp",
|
||||||
phoneNumberId: phoneNumber!.id,
|
phoneNumberId: currentPhoneNumber!.id,
|
||||||
from: phoneNumber!.number,
|
from: currentPhoneNumber!.number,
|
||||||
to: recipient,
|
to: recipient,
|
||||||
recipient,
|
recipient,
|
||||||
sentAt: new Date(),
|
sentAt: new Date(),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import type { LoaderFunction } from "@remix-run/node";
|
import type { LoaderFunction } from "@remix-run/node";
|
||||||
import { json } from "superjson-remix";
|
import { json } from "superjson-remix";
|
||||||
import { parsePhoneNumber } from "awesome-phonenumber";
|
import { parsePhoneNumber } from "awesome-phonenumber";
|
||||||
import { type Message, Prisma } from "@prisma/client";
|
import { type Message, type PhoneNumber, Prisma } from "@prisma/client";
|
||||||
|
|
||||||
import db from "~/utils/db.server";
|
import db from "~/utils/db.server";
|
||||||
import { requireLoggedIn } from "~/utils/auth.server";
|
import { requireLoggedIn } from "~/utils/auth.server";
|
||||||
@ -15,6 +15,7 @@ type ConversationType = {
|
|||||||
|
|
||||||
export type ConversationLoaderData = {
|
export type ConversationLoaderData = {
|
||||||
conversation: ConversationType;
|
conversation: ConversationType;
|
||||||
|
currentPhoneNumber: Pick<PhoneNumber, "id" | "number">;
|
||||||
};
|
};
|
||||||
|
|
||||||
const loader: LoaderFunction = async ({ request, params }) => {
|
const loader: LoaderFunction = async ({ request, params }) => {
|
||||||
@ -24,10 +25,26 @@ const loader: LoaderFunction = async ({ request, params }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const twilioAccountSid = twilio.accountSid;
|
const twilioAccountSid = twilio.accountSid;
|
||||||
|
const currentPhoneNumber = await db.phoneNumber.findUnique({
|
||||||
|
where: {
|
||||||
|
twilioAccountSid_isCurrent: {
|
||||||
|
twilioAccountSid,
|
||||||
|
isCurrent: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
number: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!currentPhoneNumber) {
|
||||||
|
return redirect("/messages");
|
||||||
|
}
|
||||||
|
|
||||||
const recipient = decodeURIComponent(params.recipient ?? "");
|
const recipient = decodeURIComponent(params.recipient ?? "");
|
||||||
const conversation = await getConversation(recipient);
|
const conversation = await getConversation(recipient);
|
||||||
|
|
||||||
return json<ConversationLoaderData>({ conversation });
|
return json<ConversationLoaderData>({ conversation, currentPhoneNumber });
|
||||||
|
|
||||||
async function getConversation(recipient: string): Promise<ConversationType> {
|
async function getConversation(recipient: string): Promise<ConversationType> {
|
||||||
const phoneNumber = await db.phoneNumber.findUnique({
|
const phoneNumber = await db.phoneNumber.findUnique({
|
||||||
|
@ -19,12 +19,10 @@ type Conversation = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const loader: LoaderFunction = async ({ request }) => {
|
const loader: LoaderFunction = async ({ request }) => {
|
||||||
const sessionData = await requireLoggedIn(request);
|
const { twilio } = await requireLoggedIn(request);
|
||||||
const phoneNumber =
|
const phoneNumber = await db.phoneNumber.findUnique({
|
||||||
sessionData.phoneNumber &&
|
where: { twilioAccountSid_isCurrent: { twilioAccountSid: twilio?.accountSid ?? "", isCurrent: true } },
|
||||||
(await db.phoneNumber.findUnique({
|
});
|
||||||
where: { id: sessionData.phoneNumber.id },
|
|
||||||
}));
|
|
||||||
return json<MessagesLoaderData>({
|
return json<MessagesLoaderData>({
|
||||||
hasPhoneNumber: Boolean(phoneNumber),
|
hasPhoneNumber: Boolean(phoneNumber),
|
||||||
isFetchingMessages: phoneNumber?.isFetchingMessages ?? null,
|
isFetchingMessages: phoneNumber?.isFetchingMessages ?? null,
|
||||||
|
@ -26,20 +26,12 @@ export type PhoneCallsLoaderData = {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const loader: LoaderFunction = async ({ request }) => {
|
const loader: LoaderFunction = async ({ request }) => {
|
||||||
const sessionData = await requireLoggedIn(request);
|
const { twilio } = await requireLoggedIn(request);
|
||||||
const hasOngoingSubscription = true; // TODO
|
|
||||||
const hasPhoneNumber = Boolean(sessionData.phoneNumber);
|
|
||||||
if (!sessionData.phoneNumber) {
|
|
||||||
return json<PhoneCallsLoaderData>({
|
|
||||||
hasOngoingSubscription,
|
|
||||||
hasPhoneNumber: false,
|
|
||||||
isFetchingCalls: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const phoneNumber = await db.phoneNumber.findUnique({
|
const phoneNumber = await db.phoneNumber.findUnique({
|
||||||
where: { id: sessionData.phoneNumber.id },
|
where: { twilioAccountSid_isCurrent: { twilioAccountSid: twilio?.accountSid ?? "", isCurrent: true } },
|
||||||
});
|
});
|
||||||
|
const hasPhoneNumber = Boolean(phoneNumber);
|
||||||
|
const hasOngoingSubscription = true; // TODO
|
||||||
if (!phoneNumber || phoneNumber.isFetchingCalls) {
|
if (!phoneNumber || phoneNumber.isFetchingCalls) {
|
||||||
return json<PhoneCallsLoaderData>({
|
return json<PhoneCallsLoaderData>({
|
||||||
hasOngoingSubscription,
|
hasOngoingSubscription,
|
||||||
|
@ -75,16 +75,8 @@ async function setPhoneNumber(request: Request, formData: unknown) {
|
|||||||
phoneNumberId: validation.data.phoneNumberSid,
|
phoneNumberId: validation.data.phoneNumberSid,
|
||||||
organizationId: organization.id,
|
organizationId: organization.id,
|
||||||
});
|
});
|
||||||
const { session } = await refreshSessionData(request);
|
|
||||||
|
|
||||||
return json<SetPhoneNumberActionData>(
|
return json<SetPhoneNumberActionData>({ setPhoneNumber: { submitted: true } });
|
||||||
{ setPhoneNumber: { submitted: true } },
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
"Set-Cookie": await commitSession(session),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SetTwilioCredentialsActionData = FormActionData<typeof validations, "setTwilioCredentials">;
|
export type SetTwilioCredentialsActionData = FormActionData<typeof validations, "setTwilioCredentials">;
|
||||||
|
@ -10,7 +10,7 @@ import type { SetPhoneNumberActionData } from "~/features/settings/actions/phone
|
|||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
|
||||||
export default function PhoneNumberForm() {
|
export default function PhoneNumberForm() {
|
||||||
const { twilio, phoneNumber } = useSession();
|
const { twilio } = useSession();
|
||||||
const fetcher = useFetcher();
|
const fetcher = useFetcher();
|
||||||
const transition = useTransition();
|
const transition = useTransition();
|
||||||
const actionData = useActionData<SetPhoneNumberActionData>()?.setPhoneNumber;
|
const actionData = useActionData<SetPhoneNumberActionData>()?.setPhoneNumber;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { redirect, type Session } from "@remix-run/node";
|
import { redirect, type Session } from "@remix-run/node";
|
||||||
import type { FormStrategyVerifyParams } from "remix-auth-form";
|
import type { FormStrategyVerifyParams } from "remix-auth-form";
|
||||||
import SecurePassword from "secure-password";
|
import SecurePassword from "secure-password";
|
||||||
import type { MembershipRole, Organization, PhoneNumber, TwilioAccount, User } from "@prisma/client";
|
import type { MembershipRole, Organization, TwilioAccount, User } from "@prisma/client";
|
||||||
|
|
||||||
import db from "./db.server";
|
import db from "./db.server";
|
||||||
import logger from "./logger.server";
|
import logger from "./logger.server";
|
||||||
@ -11,12 +11,10 @@ import { commitSession, destroySession, getSession } from "./session.server";
|
|||||||
|
|
||||||
type SessionTwilioAccount = Pick<TwilioAccount, "accountSid" | "authToken">;
|
type SessionTwilioAccount = Pick<TwilioAccount, "accountSid" | "authToken">;
|
||||||
type SessionOrganization = Pick<Organization, "id"> & { role: MembershipRole; membershipId: string };
|
type SessionOrganization = Pick<Organization, "id"> & { role: MembershipRole; membershipId: string };
|
||||||
type SessionPhoneNumber = Pick<PhoneNumber, "id" | "number">;
|
|
||||||
export type SessionUser = Pick<User, "id" | "role" | "email" | "fullName">;
|
export type SessionUser = Pick<User, "id" | "role" | "email" | "fullName">;
|
||||||
export type SessionData = {
|
export type SessionData = {
|
||||||
user: SessionUser;
|
user: SessionUser;
|
||||||
organization: SessionOrganization;
|
organization: SessionOrganization;
|
||||||
phoneNumber: SessionPhoneNumber | null;
|
|
||||||
twilio: SessionTwilioAccount | null;
|
twilio: SessionTwilioAccount | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -198,13 +196,9 @@ async function buildSessionData(id: string): Promise<SessionData> {
|
|||||||
membershipId: membership.id,
|
membershipId: membership.id,
|
||||||
}));
|
}));
|
||||||
const { twilioAccount, ...organization } = organizations[0];
|
const { twilioAccount, ...organization } = organizations[0];
|
||||||
const phoneNumber = await db.phoneNumber.findUnique({
|
|
||||||
where: { twilioAccountSid_isCurrent: { twilioAccountSid: twilioAccount?.accountSid ?? "", isCurrent: true } },
|
|
||||||
});
|
|
||||||
return {
|
return {
|
||||||
user: rest,
|
user: rest,
|
||||||
organization,
|
organization,
|
||||||
phoneNumber,
|
|
||||||
twilio: twilioAccount,
|
twilio: twilioAccount,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user