mirror of
https://github.com/fergalmoran/radio-otherway.git
synced 2025-12-22 09:50:29 +00:00
Add notification options
This commit is contained in:
@@ -14,9 +14,9 @@
|
||||
"dependencies": {
|
||||
"@babel/plugin-transform-react-display-name": "^7.18.6",
|
||||
"@headlessui/react": "^1.7.11",
|
||||
"@next/font": "13.2.0",
|
||||
"@next/font": "13.2.3",
|
||||
"@types/feather-icons": "^4.29.1",
|
||||
"@types/node": "18.14.2",
|
||||
"@types/node": "18.14.6",
|
||||
"@types/react": "18.0.28",
|
||||
"@types/react-dom": "18.0.11",
|
||||
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||
@@ -64,7 +64,7 @@
|
||||
"@hookform/devtools": "^4.3.0",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"eslint-config-prettier": "^8.6.0",
|
||||
"googleapis": "111.0.0",
|
||||
"googleapis": "112.0.0",
|
||||
"postcss": "^8.4.21",
|
||||
"prettier": "^2.8.4",
|
||||
"prettier-plugin-tailwindcss": "^0.2.2",
|
||||
|
||||
BIN
web/public/img/default-show.png
Normal file
BIN
web/public/img/default-show.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 865 KiB |
@@ -12,6 +12,7 @@ import OtherwayAppProvider from "@/components/providers/OtherwayAppProvider";
|
||||
import { ThemeProvider } from "@/components/providers";
|
||||
import { FirebaseAppProvider } from "reactfire";
|
||||
import { Theme } from "react-daisyui";
|
||||
import AuthProfileProvider from "@/lib/auth/AuthProfileProvider";
|
||||
|
||||
// only initialize when in the browser
|
||||
const font = Raleway({
|
||||
@@ -35,15 +36,17 @@ const RootLayout = ({ children }: React.PropsWithChildren) => {
|
||||
<ThemeProvider>
|
||||
<FirebaseAppProvider firebaseConfig={firebaseConfig}>
|
||||
<OtherwayAppProvider>
|
||||
<Toaster />
|
||||
<PushNotificationWrapper>
|
||||
<div className="flex min-h-screen flex-col bg-base-100">
|
||||
<NavBar />
|
||||
<div className="grow place-items-center items-end bg-base-200 text-base-content">
|
||||
<main className=" text-base-content">{children}</main>
|
||||
<AuthProfileProvider>
|
||||
<Toaster />
|
||||
<PushNotificationWrapper>
|
||||
<div className="flex min-h-screen flex-col bg-base-100">
|
||||
<NavBar />
|
||||
<div className="grow place-items-center items-end bg-base-200 text-base-content">
|
||||
<main className=" text-base-content">{children}</main>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</PushNotificationWrapper>
|
||||
</PushNotificationWrapper>
|
||||
</AuthProfileProvider>
|
||||
</OtherwayAppProvider>
|
||||
</FirebaseAppProvider>
|
||||
</ThemeProvider>
|
||||
|
||||
@@ -1,32 +1,10 @@
|
||||
import React from "react";
|
||||
import { useState } from "react";
|
||||
|
||||
const LogRocket = require("logrocket");
|
||||
import packageJson from "../../package.json";
|
||||
|
||||
const Loading = () => {
|
||||
if (process.env.LOGROCKET_ID && window !== undefined) {
|
||||
LogRocket.init(process.env.LOGROCKET_ID, {
|
||||
release: packageJson.version,
|
||||
rootHostname: "radio-otherway.fergl.ie",
|
||||
console: {
|
||||
shouldAggregateConsoleErrors: true,
|
||||
},
|
||||
network: {
|
||||
requestSanitizer: (request: any) => {
|
||||
// if the url contains token 'ignore' it
|
||||
if (request.url.toLowerCase().indexOf("token") !== -1) {
|
||||
// ignore the request response pair
|
||||
return null;
|
||||
}
|
||||
// remove Authorization header from logrocket
|
||||
request.headers.Authorization = undefined;
|
||||
// otherwise log the request normally
|
||||
return request;
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div role="status">
|
||||
<svg
|
||||
|
||||
@@ -3,6 +3,7 @@ import React from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { IoLogoFacebook, IoLogoGoogle, IoLogoTwitter } from "react-icons/io";
|
||||
import useFirebaseAuth from "@/lib/auth/signin";
|
||||
import { FacebookButton, GoogleButton, TwitterButton } from "@/components/widgets/buttons/social";
|
||||
|
||||
const LoginPage = () => {
|
||||
const router = useRouter();
|
||||
@@ -15,7 +16,7 @@ const LoginPage = () => {
|
||||
signInWithTwitter,
|
||||
signInWithFacebook,
|
||||
signIn,
|
||||
getUserProfile,
|
||||
getUserProfile
|
||||
} = useFirebaseAuth();
|
||||
const login = async (
|
||||
event: React.SyntheticEvent<HTMLButtonElement>
|
||||
@@ -25,7 +26,7 @@ const LoginPage = () => {
|
||||
return (
|
||||
<div className="font-body max-w-lg rounded-md bg-base-100 p-10 text-base-content shadow-md md:flex-1">
|
||||
<h3 className="font-title my-4 text-2xl font-semibold">Account Login</h3>
|
||||
<form action="#" className="flex flex-col space-y-5">
|
||||
<div className="flex flex-col space-y-5">
|
||||
<div className="flex flex-col space-y-1">
|
||||
<label htmlFor="email" className="text-sm">
|
||||
Email address
|
||||
@@ -83,42 +84,9 @@ const LoginPage = () => {
|
||||
<span className="h-px w-14 bg-gray-400" />
|
||||
</span>
|
||||
<div className="flex items-center justify-center gap-4">
|
||||
<button
|
||||
type="button"
|
||||
className="btn w-1/3 gap-2"
|
||||
onClick={signInWithTwitter}
|
||||
>
|
||||
<div className="text-base-content">
|
||||
<IoLogoTwitter />
|
||||
</div>
|
||||
<span className="text-sm font-medium text-base-content">
|
||||
Twitter
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="btn w-1/3 gap-2"
|
||||
onClick={signInWithGoogle}
|
||||
>
|
||||
<div className="text-base-content">
|
||||
<IoLogoGoogle />
|
||||
</div>
|
||||
<span className="text-sm font-medium text-base-content">
|
||||
Gmail
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="btn w-1/3 gap-2"
|
||||
onClick={signInWithFacebook}
|
||||
>
|
||||
<div className="text-base-content">
|
||||
<IoLogoFacebook />
|
||||
</div>
|
||||
<span className="text-sm font-medium text-base-content">
|
||||
Facebook
|
||||
</span>
|
||||
</button>
|
||||
<TwitterButton onClick={signInWithTwitter} />
|
||||
<GoogleButton onClick={signInWithGoogle} />
|
||||
<FacebookButton onClick={signInWithFacebook} />
|
||||
</div>
|
||||
{error && (
|
||||
<div className="alert alert-error shadow-lg">
|
||||
@@ -141,7 +109,7 @@ const LoginPage = () => {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -9,10 +9,11 @@ import UpcomingShowsTable from "./UpcomingShowsTable";
|
||||
interface IHomePageComponentProps {
|
||||
shows: Show[] | undefined;
|
||||
}
|
||||
|
||||
const HomePageComponent = ({ shows }: IHomePageComponentProps) => {
|
||||
const _getLayout = () => {
|
||||
if (!shows) {
|
||||
return <Loading />;
|
||||
return <div className="p-4"><Loading /></div>;
|
||||
}
|
||||
if (shows.length === 0) {
|
||||
return <NoShows />;
|
||||
|
||||
@@ -1,41 +1,47 @@
|
||||
import React from "react";
|
||||
import { RemindMeButton } from "@/components/widgets";
|
||||
import { getMonthName, getTime } from "@/lib/util/dateUtils";
|
||||
import Image from "next/image";
|
||||
import { Show } from "@/models";
|
||||
|
||||
interface IUpcomingShowsTableProps {
|
||||
shows: Show[];
|
||||
}
|
||||
|
||||
const UpcomingShowsTable = ({ shows }: IUpcomingShowsTableProps) => {
|
||||
return (
|
||||
<table className="table w-full">
|
||||
{/* head */}
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Who?</th>
|
||||
<th>When?</th>
|
||||
<th>What?</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Who?</th>
|
||||
<th>When?</th>
|
||||
<th>What?</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{/* row 1 */}
|
||||
{shows &&
|
||||
shows.map((show: Show) => (
|
||||
<tr key={show.id}>
|
||||
<th>{show.creator}</th>
|
||||
<td className="pl-5 pr-3 whitespace-no-wrap">
|
||||
<div className="text-gray-400">
|
||||
{`${new Date(show.date).getDay()} ${getMonthName(show.date)}`}{" "}
|
||||
@ {getTime(show.date)}
|
||||
</div>
|
||||
</td>
|
||||
<td>{show.title}</td>
|
||||
<th>
|
||||
<RemindMeButton showId={show.id} />
|
||||
</th>
|
||||
</tr>
|
||||
))}
|
||||
{/* row 1 */}
|
||||
{shows &&
|
||||
shows.map((show: Show) => (
|
||||
<tr key={show.id}>
|
||||
<th>
|
||||
<Image alt="Show" src={show.image ? show.image : "/img/default-show.png"} width={48} height={48} />
|
||||
</th>
|
||||
<th>{show.creator}</th>
|
||||
<td className="pl-5 pr-3 whitespace-no-wrap">
|
||||
<div className="text-gray-400">
|
||||
{`${new Date(show.date).getDay()} ${getMonthName(show.date)}`}{" "}
|
||||
@ {getTime(show.date)}
|
||||
</div>
|
||||
</td>
|
||||
<td>{show.title}</td>
|
||||
<th>
|
||||
<RemindMeButton showId={show.id} />
|
||||
</th>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
"use client";
|
||||
import React, { useEffect, useMemo } from "react";
|
||||
import React, { useContext, useEffect, useMemo } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { User, Bell } from "react-feather";
|
||||
import classNames from "classnames";
|
||||
import ProfilePageComponentProfile from "./ProfilePageComponentProfile";
|
||||
import ProfilePageComponentNotifications from "./ProfilePageComponentNotifications";
|
||||
import { SubmitHandler, useForm } from "react-hook-form";
|
||||
import { doc, setDoc } from "firebase/firestore";
|
||||
import ToastService from "@/components/widgets/toast";
|
||||
import logger from "@/lib/util/logging";
|
||||
import { removeUndefinedProperties } from "@/lib/util/objectUtils";
|
||||
import { AuthProfileContext } from "@/lib/auth/AuthProfileProvider";
|
||||
import { useUser } from "reactfire";
|
||||
import Loading from "@/app/loading";
|
||||
import { Users } from "@/lib/db/collections";
|
||||
|
||||
export type ProfileForm = {
|
||||
displayName: string;
|
||||
@@ -18,155 +21,145 @@ export type ProfileForm = {
|
||||
photoURL: string;
|
||||
headerPhotoURL: string;
|
||||
mobileNumber: string;
|
||||
notificationsBrowser: boolean;
|
||||
notificationsMobile: boolean;
|
||||
notificationsWhatsapp: boolean;
|
||||
notificationsEmail: boolean;
|
||||
};
|
||||
import { useUser } from "reactfire";
|
||||
|
||||
const ProfilePageComponent = () => {
|
||||
return <div>Profile</div>;
|
||||
// const { status, data: profile } = useUser();
|
||||
|
||||
// const router = useRouter();
|
||||
// React.useEffect(() => {
|
||||
// if (status !== "loading" && !profile) {
|
||||
// router.push("/");
|
||||
// }
|
||||
// }, [status, profile, router]);
|
||||
const { profile } = useContext(AuthProfileContext);
|
||||
const { status, data: user } = useUser();
|
||||
const router = useRouter();
|
||||
const subNavigation = [
|
||||
{ name: "profile", title: "Profile", icon: User },
|
||||
{
|
||||
name: "notifications",
|
||||
title: "Notifications",
|
||||
icon: Bell
|
||||
}
|
||||
];
|
||||
|
||||
// const subNavigation = [
|
||||
// { name: "profile", title: "Profile", icon: User },
|
||||
// {
|
||||
// name: "notifications",
|
||||
// title: "Notifications",
|
||||
// icon: Bell,
|
||||
// },
|
||||
// ];
|
||||
// const [selectedItem, setSelectedItem] = React.useState("profile");
|
||||
// const {
|
||||
// register,
|
||||
// handleSubmit,
|
||||
// setValue,
|
||||
// reset,
|
||||
// watch,
|
||||
// control,
|
||||
// formState: { errors },
|
||||
// } = useForm<ProfileForm>({
|
||||
// defaultValues: useMemo(() => {
|
||||
// return profile;
|
||||
// }, [profile]),
|
||||
// });
|
||||
const [selectedItem, setSelectedItem] = React.useState("profile");
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
setValue,
|
||||
reset,
|
||||
watch,
|
||||
control,
|
||||
formState: { errors }
|
||||
} = useForm<ProfileForm>({
|
||||
defaultValues: useMemo(() => {
|
||||
return profile;
|
||||
}, [profile])
|
||||
});
|
||||
|
||||
// useEffect(() => {
|
||||
// if (profile) {
|
||||
// reset(profile);
|
||||
// }
|
||||
// }, [profile, reset]);
|
||||
// const onSubmit: SubmitHandler<ProfileForm> = async (data) => {
|
||||
// console.log(data);
|
||||
// try {
|
||||
// const newProfile = removeUndefinedProperties({
|
||||
// displayName: data.displayName,
|
||||
// email: data.email,
|
||||
// about: data.about,
|
||||
// photoURL: data.photoURL,
|
||||
// headerPhotoURL: data.headerPhotoURL,
|
||||
// mobileNumber: data.mobileNumber,
|
||||
// lastSeen: new Date(),
|
||||
// });
|
||||
// const result = await setDoc(
|
||||
// doc(users, profile?.id),
|
||||
// Object.assign({}, newProfile),
|
||||
// {
|
||||
// merge: true,
|
||||
// }
|
||||
// );
|
||||
// console.log("ProfilePageComponentProfile", "_submitProfileForm", result);
|
||||
// ToastService.success("Successfully updated your profile", "Success");
|
||||
// } catch (err) {
|
||||
// logger.error("ProfilePageComponentProfile", "_submitProfileForm", err);
|
||||
// ToastService.error("Failed to update your profile.");
|
||||
// }
|
||||
// };
|
||||
useEffect(() => {
|
||||
if (profile) {
|
||||
console.log("ProfilePageComponent", "profileChanged", profile);
|
||||
reset(profile);
|
||||
}
|
||||
}, [profile, reset]);
|
||||
const onSubmit: SubmitHandler<ProfileForm> = async (data) => {
|
||||
console.log(data);
|
||||
try {
|
||||
const newProfile = removeUndefinedProperties({
|
||||
displayName: data.displayName,
|
||||
email: data.email,
|
||||
about: data.about,
|
||||
photoURL: data.photoURL,
|
||||
headerPhotoURL: data.headerPhotoURL,
|
||||
mobileNumber: data.mobileNumber,
|
||||
lastSeen: new Date(),
|
||||
notificationsEmail: data.notificationsEmail,
|
||||
notificationsMobile: data.notificationsMobile,
|
||||
notificationsWhatsapp: data.notificationsWhatsapp,
|
||||
notificationsBrowser: data.notificationsBrowser
|
||||
});
|
||||
console.log("ProfilePageComponent", "Updating profile", newProfile);
|
||||
if (profile?.id) {
|
||||
const result = await Users.set(profile.id, newProfile);
|
||||
}
|
||||
ToastService.success("Successfully updated your profile", "Success");
|
||||
} catch (err) {
|
||||
logger.error("ProfilePageComponentProfile", "_submitProfileForm", err);
|
||||
ToastService.error("Failed to update your profile.");
|
||||
}
|
||||
};
|
||||
|
||||
// useEffect(() => {}, [selectedItem]);
|
||||
// const _getView = () => {
|
||||
// if (status === "loading") {
|
||||
// return <div>Loading</div>;
|
||||
// } else if (status === "success" && !profile) {
|
||||
// return <div>Rerouting</div>;
|
||||
// } else if (status === "success" && profile) {
|
||||
// return (
|
||||
// <div className="pt-4 overflow-hidden">
|
||||
// <div className="justify-center flex-1 px-2 mx-2 md:flex md:justify-start">
|
||||
// <span className="text-2xl font-bold">Your Profile</span>
|
||||
// </div>
|
||||
// <div className="mt-1 divider" />
|
||||
// <div className="divide-y lg:grid lg:grid-cols-12 lg:divide-y-0 lg:divide-x">
|
||||
// <aside className="py-6 lg:col-span-3">
|
||||
// <nav className="space-y-1">
|
||||
// {subNavigation.map((item) => (
|
||||
// <a
|
||||
// onClick={() => setSelectedItem(item.name)}
|
||||
// key={item.name}
|
||||
// className={classNames(
|
||||
// item.name === selectedItem
|
||||
// ? "border-teal-600 bg-base-100 text-teal-700 hover:text-teal-700"
|
||||
// : "border-transparent hover:text-base-300",
|
||||
// "group flex cursor-pointer items-center border-l-4 px-3 py-2 text-sm font-medium hover:bg-accent"
|
||||
// )}
|
||||
// aria-current={item.name ? "page" : undefined}
|
||||
// >
|
||||
// <item.icon
|
||||
// className={classNames(
|
||||
// item.name === selectedItem
|
||||
// ? "text-teal-500 group-hover:text-base-100"
|
||||
// : "text-base-content group-hover:text-base-100",
|
||||
// "-ml-1 mr-3 h-6 w-6 flex-shrink-0"
|
||||
// )}
|
||||
// aria-hidden="true"
|
||||
// />
|
||||
// <span className="truncate">{item.title}</span>
|
||||
// </a>
|
||||
// ))}
|
||||
// </nav>
|
||||
// </aside>
|
||||
useEffect(() => {
|
||||
}, [selectedItem]);
|
||||
const _getView = () => {
|
||||
|
||||
// <div className="p-4 divide-y lg:col-span-9">
|
||||
// <form onSubmit={handleSubmit(onSubmit)}>
|
||||
// {selectedItem === "profile" ? (
|
||||
// <ProfilePageComponentProfile
|
||||
// setValue={setValue}
|
||||
// register={register}
|
||||
// profile={profile}
|
||||
// />
|
||||
// ) : (
|
||||
// <ProfilePageComponentNotifications
|
||||
// register={register}
|
||||
// control={control}
|
||||
// profile={profile}
|
||||
// />
|
||||
// )}
|
||||
// <div className="pt-5">
|
||||
// <div className="flex justify-end space-x-2">
|
||||
// <button type="button" className="btn-warning btn">
|
||||
// Cancel
|
||||
// </button>
|
||||
// <button type="submit" className="btn-success btn">
|
||||
// Save
|
||||
// </button>
|
||||
// </div>
|
||||
// </div>
|
||||
// </form>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// );
|
||||
// } else {
|
||||
// return (
|
||||
// <div>
|
||||
// <h1>This is weird</h1>
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
// };
|
||||
// return _getView();
|
||||
return profile ? (
|
||||
<div className="pt-4 overflow-hidden">
|
||||
<div className="justify-center flex-1 px-2 mx-2 md:flex md:justify-start">
|
||||
<span className="text-2xl font-bold">Your Profile</span>
|
||||
</div>
|
||||
<div className="mt-1 divider" />
|
||||
<div className="divide-y lg:grid lg:grid-cols-12 lg:divide-y-0 lg:divide-x">
|
||||
<aside className="py-6 lg:col-span-3">
|
||||
<nav className="space-y-1">
|
||||
{subNavigation.map((item) => (
|
||||
<a
|
||||
onClick={() => setSelectedItem(item.name)}
|
||||
key={item.name}
|
||||
className={classNames(
|
||||
item.name === selectedItem
|
||||
? "border-teal-600 bg-base-100 text-teal-700 hover:text-teal-700"
|
||||
: "border-transparent hover:text-base-300",
|
||||
"group flex cursor-pointer items-center border-l-4 px-3 py-2 text-sm font-medium hover:bg-accent"
|
||||
)}
|
||||
aria-current={item.name ? "page" : undefined}
|
||||
>
|
||||
<item.icon
|
||||
className={classNames(
|
||||
item.name === selectedItem
|
||||
? "text-teal-500 group-hover:text-base-100"
|
||||
: "text-base-content group-hover:text-base-100",
|
||||
"-ml-1 mr-3 h-6 w-6 flex-shrink-0"
|
||||
)}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span className="truncate">{item.title}</span>
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
<div className="p-4 divide-y lg:col-span-9">
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
{selectedItem === "profile" ? (
|
||||
<ProfilePageComponentProfile
|
||||
setValue={setValue}
|
||||
register={register}
|
||||
profile={profile}
|
||||
/>
|
||||
) : (
|
||||
<ProfilePageComponentNotifications
|
||||
register={register}
|
||||
control={control}
|
||||
profile={profile}
|
||||
/>
|
||||
)}
|
||||
<div className="pt-5">
|
||||
<div className="flex justify-end space-x-2">
|
||||
<button type="button" className="btn-warning btn">
|
||||
Cancel
|
||||
</button>
|
||||
<button type="submit" className="btn-success btn">
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : <Loading />;
|
||||
};
|
||||
return _getView();
|
||||
};
|
||||
export default ProfilePageComponent;
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from "react";
|
||||
import { HeadingSubComponent } from "@/components/widgets/text";
|
||||
import {
|
||||
PhoneNumber,
|
||||
RequestPushNotifications,
|
||||
RequestPushNotifications
|
||||
} from "@/components/widgets/notifications";
|
||||
import { UseFormRegister } from "react-hook-form";
|
||||
import { ProfileForm } from "@/components/pages/profile/ProfilePageComponent";
|
||||
@@ -13,11 +13,12 @@ interface IProfilePageComponentNotificationsProps {
|
||||
control: any;
|
||||
profile: Profile;
|
||||
}
|
||||
|
||||
const ProfilePageComponentNotifications = ({
|
||||
register,
|
||||
control,
|
||||
profile,
|
||||
}: IProfilePageComponentNotificationsProps) => {
|
||||
register,
|
||||
control,
|
||||
profile
|
||||
}: IProfilePageComponentNotificationsProps) => {
|
||||
const [notificationPermissionsGranted, setNotificationPermissionsGranted] =
|
||||
React.useState(Notification.permission !== "granted");
|
||||
|
||||
@@ -61,6 +62,44 @@ const ProfilePageComponentNotifications = ({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-x-3 sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:border-t sm:pt-5">
|
||||
<HeadingSubComponent
|
||||
title="Notification methods"
|
||||
subHeading="Where you'd like to see notifications when a show is starting"
|
||||
/>
|
||||
<div className="mt-1 sm:col-span-2 sm:mt-0">
|
||||
<div className="flex flex-grow max-w-lg rounded-md shadow-sm">
|
||||
<div className="form-control">
|
||||
<label className="cursor-pointer label">
|
||||
<span className="label-text mr-2">Browser</span>
|
||||
<input type="checkbox" id="notificationsBrowser"
|
||||
className="toggle toggle-primary" {...register("notificationsBrowser")} />
|
||||
</label>
|
||||
</div>
|
||||
<div className="form-control">
|
||||
<label className="cursor-pointer label">
|
||||
<span className="label-text mr-2">Mobile</span>
|
||||
<input type="checkbox" id="notificationsMobile"
|
||||
className="toggle toggle-primary" {...register("notificationsMobile")} />
|
||||
</label>
|
||||
</div>
|
||||
<div className="form-control">
|
||||
<label className="cursor-pointer label">
|
||||
<span className="label-text mr-2">WhatsApp</span>
|
||||
<input type="checkbox" id="notificationsWhatsapp"
|
||||
className="toggle toggle-primary" {...register("notificationsWhatsapp")} />
|
||||
</label>
|
||||
</div>
|
||||
<div className="form-control">
|
||||
<label className="cursor-pointer label">
|
||||
<span className="label-text mr-2">Email</span>
|
||||
<input type="checkbox" id="notificationsEmail"
|
||||
className="toggle toggle-primary" {...register("notificationsEmail")} />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -12,11 +12,12 @@ interface IProfilePageComponentProfileProps {
|
||||
register: UseFormRegister<ProfileForm>;
|
||||
setValue: UseFormSetValue<ProfileForm>;
|
||||
}
|
||||
|
||||
const ProfilePageComponentProfile = ({
|
||||
profile,
|
||||
register,
|
||||
setValue,
|
||||
}: IProfilePageComponentProfileProps) => {
|
||||
profile,
|
||||
register,
|
||||
setValue
|
||||
}: IProfilePageComponentProfileProps) => {
|
||||
const [photoURLFile, setPhotoURLFile] = useState("");
|
||||
return (
|
||||
<div className="space-y-8 divide-y sm:space-y-5">
|
||||
@@ -40,6 +41,7 @@ const ProfilePageComponentProfile = ({
|
||||
id="displayName"
|
||||
type="text"
|
||||
label="Display name"
|
||||
showLabel={false}
|
||||
{...register("displayName")}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,16 +1,47 @@
|
||||
import React from "react";
|
||||
import { AuthProvider, FirestoreProvider, useFirebaseApp } from "reactfire";
|
||||
import React, { useEffect } from "react";
|
||||
import { AuthProvider, FirestoreProvider, StorageProvider, useFirebaseApp } from "reactfire";
|
||||
import { getAuth } from "firebase/auth";
|
||||
import { getFirestore } from "firebase/firestore";
|
||||
import LogRocket from "logrocket";
|
||||
import packageJson from "../../../package.json";
|
||||
import { getStorage } from "@firebase/storage";
|
||||
|
||||
const OtherwayAppProvider = ({ children }: React.PropsWithChildren) => {
|
||||
const app = useFirebaseApp();
|
||||
const auth = getAuth(app);
|
||||
const firestore = getFirestore(app);
|
||||
|
||||
const storage = getStorage(app);
|
||||
useEffect(() => {
|
||||
if (process.env.LOGROCKET_ID && window !== undefined) {
|
||||
LogRocket.init(process.env.LOGROCKET_ID, {
|
||||
release: packageJson.version,
|
||||
rootHostname: "radio-otherway.fergl.ie",
|
||||
console: {
|
||||
shouldAggregateConsoleErrors: true
|
||||
},
|
||||
network: {
|
||||
requestSanitizer: (request: any) => {
|
||||
// if the url contains token 'ignore' it
|
||||
if (request.url.toLowerCase().indexOf("token") !== -1) {
|
||||
// ignore the request response pair
|
||||
return null;
|
||||
}
|
||||
// remove Authorization header from logrocket
|
||||
request.headers.Authorization = undefined;
|
||||
// otherwise log the request normally
|
||||
return request;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
return (
|
||||
<AuthProvider sdk={auth}>
|
||||
<FirestoreProvider sdk={firestore}>{children}</FirestoreProvider>
|
||||
<FirestoreProvider sdk={firestore}>
|
||||
<StorageProvider sdk={storage}>
|
||||
{children}
|
||||
</StorageProvider>
|
||||
</FirestoreProvider>
|
||||
</AuthProvider>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import React from "react";
|
||||
import { IoLogoFacebook } from "react-icons/io";
|
||||
|
||||
interface IBaseSocialButtonProps extends React.PropsWithChildren {
|
||||
onClick: ($event: any) => {};
|
||||
}
|
||||
|
||||
const BaseSocialButton = ({ onClick, children }: IBaseSocialButtonProps) => {
|
||||
return <button className="btn" onClick={onClick}>
|
||||
{children}
|
||||
</button>;
|
||||
|
||||
};
|
||||
|
||||
export default BaseSocialButton;
|
||||
15
web/src/components/widgets/buttons/social/FacebookButton.tsx
Normal file
15
web/src/components/widgets/buttons/social/FacebookButton.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import React from "react";
|
||||
import { IoLogoFacebook } from "react-icons/io";
|
||||
import BaseSocialButton from "@/components/widgets/buttons/social/BaseSocialButton";
|
||||
import { ISocialButtonProps } from "@/components/widgets/buttons/social/socialButtonProps";
|
||||
|
||||
const FacebookButton = ({ onClick }: ISocialButtonProps) => {
|
||||
return (
|
||||
<BaseSocialButton onClick={onClick}>
|
||||
<IoLogoFacebook className="mr-2" />
|
||||
Facebook
|
||||
</BaseSocialButton>
|
||||
);
|
||||
};
|
||||
|
||||
export default FacebookButton;
|
||||
15
web/src/components/widgets/buttons/social/GoogleButton.tsx
Normal file
15
web/src/components/widgets/buttons/social/GoogleButton.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import React from "react";
|
||||
import { ISocialButtonProps } from "./socialButtonProps";
|
||||
import { IoLogoGoogle } from "react-icons/io";
|
||||
import BaseSocialButton from "@/components/widgets/buttons/social/BaseSocialButton";
|
||||
|
||||
const GoogleButton = ({ onClick }: ISocialButtonProps) => {
|
||||
return (
|
||||
<BaseSocialButton onClick={onClick}>
|
||||
<IoLogoGoogle className="mr-2" />
|
||||
Google
|
||||
</BaseSocialButton>
|
||||
);
|
||||
};
|
||||
|
||||
export default GoogleButton;
|
||||
@@ -1,24 +1,14 @@
|
||||
import React from "react";
|
||||
import { ISocialButtonProps } from "./socialButtonProps";
|
||||
import { IoLogoTwitter } from "react-icons/io";
|
||||
import BaseSocialButton from "@/components/widgets/buttons/social/BaseSocialButton";
|
||||
|
||||
const TwitterButton = ({ onClick }: ISocialButtonProps) => {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className="btn-secondary btn mb-2 flex
|
||||
w-1/3 gap-2 rounded px-6 py-2.5 text-xs font-medium uppercase leading-normal text-white shadow-md transition duration-150 ease-in-out hover:shadow-lg focus:shadow-lg focus:outline-none focus:ring-0 active:shadow-lg"
|
||||
style={{ backgroundColor: "#1da1f2" }}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="mr-2 h-3.5 w-3.5"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z" />
|
||||
</svg>
|
||||
<BaseSocialButton onClick={onClick}>
|
||||
<IoLogoTwitter className="mr-2" />
|
||||
Twitter
|
||||
</button>
|
||||
</BaseSocialButton>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import TwitterButton from "./TwitterButton";
|
||||
import FacebookButton from "./FacebookButton";
|
||||
import GoogleButton from "./GoogleButton";
|
||||
|
||||
export { TwitterButton };
|
||||
export { TwitterButton, FacebookButton, GoogleButton };
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export interface ISocialButtonProps {
|
||||
onClick: () => {};
|
||||
onClick: ($event: any) => {};
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from "react";
|
||||
import {
|
||||
ref as storageRef,
|
||||
uploadBytesResumable,
|
||||
getDownloadURL,
|
||||
getDownloadURL
|
||||
} from "firebase/storage";
|
||||
import Image from "next/image";
|
||||
import {
|
||||
@@ -10,8 +10,9 @@ import {
|
||||
useRef,
|
||||
useState,
|
||||
forwardRef,
|
||||
ChangeEventHandler,
|
||||
ChangeEventHandler
|
||||
} from "react";
|
||||
|
||||
const path = require("path");
|
||||
import { UploadCloud } from "react-feather";
|
||||
import { getFileExtension } from "@/lib/util/fileUtils";
|
||||
@@ -20,7 +21,7 @@ import {
|
||||
Controller,
|
||||
FieldPath,
|
||||
UseFormReturn,
|
||||
UseFormSetValue,
|
||||
UseFormSetValue
|
||||
} from "react-hook-form";
|
||||
import { ProfileForm } from "@/components/pages/profile/ProfilePageComponent";
|
||||
import { useStorage } from "reactfire";
|
||||
@@ -49,7 +50,7 @@ const FirebaseImageUploader = forwardRef<
|
||||
imageUrl,
|
||||
setValue,
|
||||
onChange,
|
||||
onBlur,
|
||||
onBlur
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
@@ -140,7 +141,7 @@ const FirebaseImageUploader = forwardRef<
|
||||
isUploading,
|
||||
itemId,
|
||||
setValue,
|
||||
storage,
|
||||
storage
|
||||
]);
|
||||
|
||||
return imageType === "avatar" ? (
|
||||
@@ -151,7 +152,7 @@ const FirebaseImageUploader = forwardRef<
|
||||
<Image
|
||||
alt="Existing image"
|
||||
src={imageUrl}
|
||||
className="w-full h-full "
|
||||
className="w-full h-full"
|
||||
width={48}
|
||||
height={48}
|
||||
/>
|
||||
@@ -161,7 +162,8 @@ const FirebaseImageUploader = forwardRef<
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M24 20.993V24H0v-2.996A14.977 14.977 0 0112.004 15c4.904 0 9.26 2.354 11.996 5.993zM16.002 8.999a4 4 0 11-8 0 4 4 0 018 0z" />
|
||||
<path
|
||||
d="M24 20.993V24H0v-2.996A14.977 14.977 0 0112.004 15c4.904 0 9.26 2.354 11.996 5.993zM16.002 8.999a4 4 0 11-8 0 4 4 0 018 0z" />
|
||||
</svg>
|
||||
)}
|
||||
</span>
|
||||
|
||||
@@ -15,6 +15,7 @@ const InputText = forwardRef<HTMLInputElement, ITextInputProps>(
|
||||
)}
|
||||
<input
|
||||
id={id}
|
||||
name={id}
|
||||
className="w-full input-bordered input"
|
||||
type={type || "text"}
|
||||
placeholder={placeholder || ""}
|
||||
|
||||
44
web/src/lib/auth/AuthProfileProvider.tsx
Normal file
44
web/src/lib/auth/AuthProfileProvider.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import React, { createContext, useEffect, useReducer, useState } from "react";
|
||||
import { Profile } from "@/models";
|
||||
import { useUser } from "reactfire";
|
||||
import useFirebaseAuth from "@/lib/auth/signin";
|
||||
import logger from "@/lib/util/logging";
|
||||
|
||||
interface IAuthProfileProviderState {
|
||||
profile: Profile | undefined;
|
||||
setProfile: (profile: Profile | undefined) => void;
|
||||
}
|
||||
|
||||
const initialState: IAuthProfileProviderState = {
|
||||
profile: undefined,
|
||||
setProfile: profile => {
|
||||
}
|
||||
};
|
||||
export const AuthProfileContext = createContext(initialState);
|
||||
|
||||
const AuthProfileProvider: React.FC<React.PropsWithChildren> = ({ children }) => {
|
||||
const { status, data: user } = useUser();
|
||||
const { getUserProfile } = useFirebaseAuth();
|
||||
useEffect(() => {
|
||||
console.log("AuthProfileProvider", "statusChanged", status);
|
||||
if (status === "success" && user) {
|
||||
const profile = getUserProfile()
|
||||
.then(profile => {
|
||||
if (profile) {
|
||||
setProfile(profile);
|
||||
}
|
||||
}).catch(err => {
|
||||
logger.debug("AuthProfileProvider", "Error loading provider", err);
|
||||
});
|
||||
}
|
||||
}, [status, user]);
|
||||
|
||||
const [profile, setProfile] = useState<Profile>();
|
||||
|
||||
return <AuthProfileContext.Provider value={{ profile, setProfile }}>
|
||||
{children}
|
||||
</AuthProfileContext.Provider>;
|
||||
};
|
||||
;
|
||||
|
||||
export default AuthProfileProvider;
|
||||
@@ -12,20 +12,20 @@ import {
|
||||
signInWithPopup,
|
||||
signOut,
|
||||
TwitterAuthProvider,
|
||||
UserCredential,
|
||||
UserCredential
|
||||
} from "firebase/auth";
|
||||
import { getDoc, doc, setDoc } from "firebase/firestore";
|
||||
import { clear } from "localforage";
|
||||
import router from "next/router";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useCallback, useContext, useEffect, useState } from "react";
|
||||
import { Users } from "../db/collections";
|
||||
import logger from "../util/logging";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { AuthProfileContext } from "@/lib/auth/AuthProfileProvider";
|
||||
|
||||
const useFirebaseAuth = () => {
|
||||
const router = useRouter();
|
||||
const auth = getAuth();
|
||||
const [errorCredential, setErrorCredential] =
|
||||
useState<OAuthCredential | null>();
|
||||
const [profile, setProfile] = useState<Profile | undefined>();
|
||||
|
||||
const [loading, setLoading] = useState(true);
|
||||
const _processSignIn = async (
|
||||
provider: any
|
||||
@@ -59,7 +59,6 @@ const useFirebaseAuth = () => {
|
||||
};
|
||||
|
||||
const clear = () => {
|
||||
setProfile(undefined);
|
||||
setLoading(true);
|
||||
};
|
||||
const getUserProfile = useCallback(async () => {
|
||||
@@ -69,31 +68,22 @@ const useFirebaseAuth = () => {
|
||||
const savedProfile = await Users.get(auth.currentUser.uid);
|
||||
const profile: Profile = new Profile(
|
||||
auth.currentUser.uid,
|
||||
(savedProfile.email || auth.currentUser.email) as string,
|
||||
(savedProfile.displayName || auth.currentUser.displayName) as string,
|
||||
(savedProfile.photoURL || auth.currentUser.photoURL) as string,
|
||||
savedProfile.about as string,
|
||||
savedProfile.mobileNumber as string,
|
||||
(savedProfile?.email || auth.currentUser.email) as string,
|
||||
(savedProfile?.displayName || auth.currentUser.displayName) as string,
|
||||
(savedProfile?.photoURL || auth.currentUser.photoURL) as string,
|
||||
savedProfile?.about as string,
|
||||
savedProfile?.mobileNumber as string,
|
||||
new Date(),
|
||||
savedProfile.deviceRegistrations
|
||||
savedProfile?.notificationsBrowser,
|
||||
savedProfile?.notificationsMobile,
|
||||
savedProfile?.notificationsWhatsapp,
|
||||
savedProfile?.notificationsEmail,
|
||||
savedProfile?.deviceRegistrations
|
||||
);
|
||||
setProfile(profile);
|
||||
await Users.set(auth.currentUser.uid, Object.assign({}, profile));
|
||||
return profile;
|
||||
}
|
||||
}, [auth.currentUser]);
|
||||
|
||||
const authStateChanged = useCallback(
|
||||
async (user: any) => {
|
||||
if (user) {
|
||||
setLoading(true);
|
||||
const profile = await getUserProfile();
|
||||
setProfile(profile);
|
||||
}
|
||||
setLoading(false);
|
||||
},
|
||||
[getUserProfile]
|
||||
);
|
||||
const signIn = (email: string, password: string) =>
|
||||
signInWithEmailAndPassword(auth, email, password);
|
||||
|
||||
@@ -126,7 +116,6 @@ const useFirebaseAuth = () => {
|
||||
if (result) {
|
||||
const credential = GoogleAuthProvider.credentialFromResult(result);
|
||||
const profile = await getUserProfile();
|
||||
setProfile(profile);
|
||||
router.push("/");
|
||||
}
|
||||
};
|
||||
@@ -136,7 +125,6 @@ const useFirebaseAuth = () => {
|
||||
if (result) {
|
||||
const credential = TwitterAuthProvider.credentialFromResult(result);
|
||||
const profile = await getUserProfile();
|
||||
setProfile(profile);
|
||||
router.push("/");
|
||||
}
|
||||
};
|
||||
@@ -144,12 +132,7 @@ const useFirebaseAuth = () => {
|
||||
const provider = new FacebookAuthProvider();
|
||||
await _processSignIn(provider);
|
||||
};
|
||||
useEffect(() => {
|
||||
const unsubscribe = onAuthStateChanged(auth, authStateChanged);
|
||||
return unsubscribe;
|
||||
}, [auth, authStateChanged]);
|
||||
return {
|
||||
profile,
|
||||
loading,
|
||||
signIn,
|
||||
signUp,
|
||||
@@ -158,7 +141,7 @@ const useFirebaseAuth = () => {
|
||||
signInWithTwitter,
|
||||
signInWithFacebook,
|
||||
// linkAccounts,
|
||||
getUserProfile,
|
||||
getUserProfile
|
||||
};
|
||||
};
|
||||
export default useFirebaseAuth;
|
||||
|
||||
@@ -1,23 +1,45 @@
|
||||
import { Show } from "@/models";
|
||||
import { createCollection } from "..";
|
||||
import { showConverter } from "../util/converters";
|
||||
import { doc, getDocs, where } from "@firebase/firestore";
|
||||
import { doc, getDocs, setDoc, where } from "@firebase/firestore";
|
||||
import { getDoc, query } from "firebase/firestore";
|
||||
import { Users } from "@/lib/db/collections/index";
|
||||
|
||||
const Shows = {
|
||||
collection: createCollection<Show>("shows").withConverter(showConverter),
|
||||
getShowById: async (showId: string) => {
|
||||
const q = await getDoc(doc(Shows.collection, showId));
|
||||
return Show.fromJson(q.data());
|
||||
},
|
||||
collection: createCollection<Show>("shows").withConverter(showConverter),
|
||||
|
||||
getUpcomingShows: async (): Promise<Show[]> => {
|
||||
const upcomingShows = await getDocs(
|
||||
query(Shows.collection, where("date", ">", new Date()))
|
||||
);
|
||||
|
||||
return upcomingShows.docs.map((s) => Show.fromJson(s.data()));
|
||||
wrapShow: async (show: Show): Promise<Show> => {
|
||||
const user = await Users.getByEmail(show.creator);
|
||||
if (user && user.displayName) {
|
||||
show.creator = user.displayName;
|
||||
show.image = user.photoURL;
|
||||
}
|
||||
return show;
|
||||
},
|
||||
set: async (showId: string, show: Show) => {
|
||||
const showRef = doc(Shows.collection, showId);
|
||||
await setDoc(
|
||||
showRef,
|
||||
show,
|
||||
{ merge: true }
|
||||
);
|
||||
},
|
||||
get: async (showId: string) => {
|
||||
const q = await getDoc(doc(Shows.collection, showId));
|
||||
return Show.fromJson(q.data());
|
||||
},
|
||||
getUpcomingShows: async (): Promise<Show[]> => {
|
||||
const upcomingShows = await getDocs(
|
||||
query(Shows.collection, where("date", ">", new Date()))
|
||||
);
|
||||
return upcomingShows.docs.map((s) => {
|
||||
const show = s.data();
|
||||
console.log("Shows", "mapping upcoming shows", show);
|
||||
return Show.fromJson(show);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
;
|
||||
|
||||
export default Shows;
|
||||
|
||||
@@ -1,20 +1,34 @@
|
||||
import { Profile } from "@/models";
|
||||
import { doc, setDoc } from "@firebase/firestore";
|
||||
import { getDoc } from "firebase/firestore";
|
||||
import { doc, getDocs, setDoc, where } from "@firebase/firestore";
|
||||
import { getDoc, query } from "firebase/firestore";
|
||||
import { createCollection } from "..";
|
||||
|
||||
const Users = {
|
||||
collection: createCollection<Profile>("users"),
|
||||
|
||||
get: async (id: string) => {
|
||||
get: async (id: string): Promise<Profile> => {
|
||||
const result = await getDoc(doc(Users.collection, id));
|
||||
return result.data();
|
||||
return Profile.fromJson(result.data());
|
||||
},
|
||||
getByEmail: async (email: string): Promise<Profile | undefined> => {
|
||||
const userQuery = await getDocs(query(Users.collection, where("email", "==", email)));
|
||||
if (userQuery.docs.length > 0) {
|
||||
const data = userQuery.docs[0].data();
|
||||
return Profile.fromJson(data);
|
||||
}
|
||||
throw Error("Unable to find user");
|
||||
},
|
||||
getNotifiable: async (): Promise<Profile[] | undefined> => {
|
||||
const usersQuery = await getDocs(
|
||||
query(Users.collection, where("mobileNumber", "!=", null))
|
||||
);
|
||||
return usersQuery.docs.map(r => Profile.fromJson(r.data()));
|
||||
},
|
||||
set: async (id: string, user: Profile) => {
|
||||
await setDoc(doc(Users.collection, id), user, {
|
||||
merge: true,
|
||||
merge: true
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
export default Users;
|
||||
|
||||
@@ -3,34 +3,18 @@ import {
|
||||
DocumentData,
|
||||
collection,
|
||||
CollectionReference,
|
||||
initializeFirestore,
|
||||
getFirestore,
|
||||
getFirestore
|
||||
} from "firebase/firestore";
|
||||
|
||||
const firebaseConfig = {
|
||||
apiKey: "AIzaSyDtk_Ym-AZroXsHvQVcdHXYyc_TvgycAWw",
|
||||
|
||||
authDomain: "radio-otherway.firebaseapp.com",
|
||||
|
||||
projectId: "radio-otherway",
|
||||
|
||||
storageBucket: "radio-otherway.appspot.com",
|
||||
|
||||
messagingSenderId: "47147490249",
|
||||
|
||||
appId: "1:47147490249:web:6243de17f52ef79126e618",
|
||||
|
||||
measurementId: "G-X3MXP6RMMC",
|
||||
|
||||
// apiKey: process.env.API_KEY,
|
||||
// authDomain: process.env.AUTH_DOMAIN,
|
||||
// projectId: process.env.PROJECT_ID,
|
||||
// storageBucket: process.env.STORAGE_BUCKET,
|
||||
// // messagingSenderId: process.env.STORAGE_BUCKET,
|
||||
// appId: process.env.APP_ID,
|
||||
// measurementId: process.env.MEASUREMENT_ID,
|
||||
apiKey: process.env.NEXT_PUBLIC_API_KEY,
|
||||
authDomain: process.env.NEXT_PUBLIC_AUTH_DOMAIN,
|
||||
projectId: process.env.NEXT_PUBLIC_PROJECT_ID,
|
||||
storageBucket: process.env.NEXT_PUBLIC_STORAGE_BUCKET,
|
||||
messagingSenderId: process.env.NEXT_PUBLIC_MESSAGING_SENDER_ID,
|
||||
appId: process.env.NEXT_PUBLIC_APP_ID,
|
||||
measurementId: process.env.NEXT_PUBLIC_MEASUREMENT_ID
|
||||
};
|
||||
|
||||
const firebaseApp = initializeApp(firebaseConfig);
|
||||
const firestore = getFirestore(firebaseApp);
|
||||
|
||||
|
||||
@@ -11,6 +11,10 @@ export default class Profile {
|
||||
mobileNumber?: string;
|
||||
lastSeen: Date;
|
||||
deviceRegistrations?: DeviceRegistration[] = [];
|
||||
notificationsBrowser: boolean;
|
||||
notificationsMobile: boolean;
|
||||
notificationsWhatsapp: boolean;
|
||||
notificationsEmail: boolean;
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
@@ -20,6 +24,10 @@ export default class Profile {
|
||||
about?: string,
|
||||
mobileNumber?: string,
|
||||
lastSeen?: Date,
|
||||
notificationsBrowser?: boolean,
|
||||
notificationsMobile?: boolean,
|
||||
notificationsWhatsapp?: boolean,
|
||||
notificationsEmail?: boolean,
|
||||
deviceRegistrations?: DeviceRegistration[]
|
||||
) {
|
||||
this.id = id;
|
||||
@@ -28,8 +36,33 @@ export default class Profile {
|
||||
this.photoURL = photoURL;
|
||||
this.about = about || "";
|
||||
this.mobileNumber = mobileNumber || "";
|
||||
this.notificationsBrowser = notificationsBrowser || false;
|
||||
this.notificationsMobile = notificationsMobile || false;
|
||||
this.notificationsWhatsapp = notificationsWhatsapp || false;
|
||||
this.notificationsEmail = notificationsEmail || false;
|
||||
|
||||
this.lastSeen = lastSeen || new Date();
|
||||
this.deviceRegistrations = deviceRegistrations || this.deviceRegistrations;
|
||||
}
|
||||
|
||||
static fromJson(r: any): Profile {
|
||||
const profile = new Profile(
|
||||
r.id,
|
||||
r.email,
|
||||
r.displayName,
|
||||
r.photoURL,
|
||||
r.about,
|
||||
r.mobileNumber,
|
||||
r.lastSeen,
|
||||
r.lastSeen
|
||||
);
|
||||
if (r.deviceRegistrations) {
|
||||
profile.deviceRegistrations = r.deviceRegistrations;
|
||||
}
|
||||
profile.notificationsBrowser = r.notificationsBrowser || false;
|
||||
profile.notificationsMobile = r.notificationsMobile || false;
|
||||
profile.notificationsWhatsapp = r.notificationsWhatsapp || false;
|
||||
profile.notificationsEmail = r.notificationsEmail || false;
|
||||
return profile;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,14 @@ export default class Show {
|
||||
title: string;
|
||||
date: string;
|
||||
creator: string;
|
||||
image?: string;
|
||||
|
||||
constructor(id: string, title: string, date: Date, creator: string) {
|
||||
constructor(id: string, title: string, date: Date, creator: string, image?: string) {
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
this.date = date.toString();
|
||||
this.creator = creator;
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
static fromJson(r: any): Show {
|
||||
@@ -16,6 +18,8 @@ export default class Show {
|
||||
r.id,
|
||||
r.title,
|
||||
new Date(r.date),
|
||||
r.creator);
|
||||
r.creator,
|
||||
r.image
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,16 +20,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
} else {
|
||||
const entries: Show[] = e?.events.map((r: any) => Show.fromJson(r));
|
||||
for (const entry of entries) {
|
||||
const showRef = doc(Shows.collection, entry.id);
|
||||
await setDoc(
|
||||
showRef,
|
||||
{
|
||||
title: entry.title,
|
||||
date: entry.date,
|
||||
creator: entry.creator,
|
||||
},
|
||||
{ merge: true }
|
||||
);
|
||||
await Shows.set(entry.id, await Shows.wrapShow(entry));
|
||||
}
|
||||
if (e?.syncToken) {
|
||||
await Settings.write("CalendarSyncToken", e?.syncToken);
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { shows, users } from "@/lib/db";
|
||||
import { Show } from "@/models";
|
||||
import { doc, getDocs } from "@firebase/firestore";
|
||||
import { getDoc, query, where } from "firebase/firestore";
|
||||
import { sendWhatsApp } from "@/lib/util/notifications/sms";
|
||||
import { StatusCodes } from "http-status-codes";
|
||||
import { Shows, Users } from "@/lib/db/collections";
|
||||
import { sendWhatsApp } from "@/lib/util/notifications/sms";
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
if (req.method !== "POST") {
|
||||
@@ -12,27 +9,19 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
}
|
||||
const { showId } = req.body;
|
||||
|
||||
const q = await getDoc(doc(shows, showId));
|
||||
const show = Show.fromJson(q.data());
|
||||
|
||||
const show = await Shows.get(showId);
|
||||
const users = await Users.getNotifiable();
|
||||
//iterate through every user and get their notifications
|
||||
//and send 'em off
|
||||
|
||||
//TODO: Move this out of here
|
||||
const usersQuery = await getDocs(
|
||||
query(users, where("mobileNumber", "!=", null))
|
||||
);
|
||||
usersQuery.forEach(async (u) => {
|
||||
const user = u.data();
|
||||
users?.forEach(user => {
|
||||
const message = (process.env.WHATSAPP_SHOW_HOUR as string)
|
||||
.replace("{{1}}", user.displayName as string)
|
||||
.replace("{{2}}", show.creator);
|
||||
if (user.mobileNumber) {
|
||||
console.log("notify", "sending notification to ", user);
|
||||
const message = (process.env.WHATSAPP_SHOW_HOUR as string)
|
||||
.replace("{{1}}", user.displayName as string)
|
||||
.replace("{{2}}", show.creator);
|
||||
|
||||
await sendWhatsApp(user.mobileNumber, message);
|
||||
sendWhatsApp(user.mobileNumber, message);
|
||||
}
|
||||
});
|
||||
|
||||
res.status(StatusCodes.OK).json({ status: "OK" });
|
||||
res.end();
|
||||
};
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { getDoc } from "firebase/firestore";
|
||||
import { StatusCodes } from "http-status-codes";
|
||||
import { NextApiRequest, NextApiResponse } from "next";
|
||||
import { firebaseConfig } from "@/lib/db";
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
res.status(StatusCodes.OK).json({ response: "Hello Sailor" });
|
||||
|
||||
res.status(StatusCodes.OK).json(firebaseConfig);
|
||||
res.end();
|
||||
};
|
||||
|
||||
|
||||
455
web/yarn.lock
455
web/yarn.lock
@@ -207,15 +207,15 @@
|
||||
dependencies:
|
||||
text-decoding "^1.0.0"
|
||||
|
||||
"@firebase/analytics-compat@0.2.3":
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/analytics-compat/-/analytics-compat-0.2.3.tgz#ed60472dcd2bfa3f2fa7a5478b63bb7aece652ed"
|
||||
integrity sha512-HmvbB4GMgh8AUlIDIo/OuFENLCGRXxMvtOueK+m8+DcfqBvG+mkii0Mi9ovo0TnMM62cy3oBYG7PHdjIQNLSLA==
|
||||
"@firebase/analytics-compat@0.2.4":
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/analytics-compat/-/analytics-compat-0.2.4.tgz#3887676286ead7b30f9880581e0144f43bc71f16"
|
||||
integrity sha512-ZN4K49QwOR8EWIUTV03VBdcVkz8sVsfJmve4g2+FEIj0kyTK0MdoVTWNOwWj9TVi2p/7FvKRKkpWxkydmi9x7g==
|
||||
dependencies:
|
||||
"@firebase/analytics" "0.9.3"
|
||||
"@firebase/analytics" "0.9.4"
|
||||
"@firebase/analytics-types" "0.8.0"
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/analytics-types@0.8.0":
|
||||
@@ -223,27 +223,27 @@
|
||||
resolved "https://registry.yarnpkg.com/@firebase/analytics-types/-/analytics-types-0.8.0.tgz#551e744a29adbc07f557306530a2ec86add6d410"
|
||||
integrity sha512-iRP+QKI2+oz3UAh4nPEq14CsEjrjD6a5+fuypjScisAh9kXKFvdJOZJDwk7kikLvWVLGEs9+kIUS4LPQV7VZVw==
|
||||
|
||||
"@firebase/analytics@0.9.3":
|
||||
version "0.9.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/analytics/-/analytics-0.9.3.tgz#ae653a6c6bcd667efd1d3cc5207e3e621d737028"
|
||||
integrity sha512-XdYHBi6RvHYVAHGyLxXX0uRPwZmGeqw1JuWS1rMEeRF/jvbxnrL81kcFAHZVRkEvG9bXAJgL2fX9wmDo3e622w==
|
||||
"@firebase/analytics@0.9.4":
|
||||
version "0.9.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/analytics/-/analytics-0.9.4.tgz#1b863bd795c3dbe3d278467e8c9dd0e6c54f37a3"
|
||||
integrity sha512-Mb2UaD0cyJ9DrTk4Okz8wqpjZuVRVXHZOjhbQcmGb8VtibXY1+jm/k3eJ21r7NqUKnjWejYM2EX+hI9+dtXGkQ==
|
||||
dependencies:
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/installations" "0.6.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/installations" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/app-check-compat@0.3.3":
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app-check-compat/-/app-check-compat-0.3.3.tgz#a1d594ec722fa81f7e11977b407a187e8afdb19a"
|
||||
integrity sha512-25AQ4W7WUL8OWas40GsABuNU622Dm1ojbfeZ03uKtLj5Af7FerJ25u7zkgm+11pc6rpr5v8E5oxEG9vmNRndEA==
|
||||
"@firebase/app-check-compat@0.3.4":
|
||||
version "0.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app-check-compat/-/app-check-compat-0.3.4.tgz#43cad88c9211a84bb98f205ba075c34acd8933c2"
|
||||
integrity sha512-s6ON0ixPKe99M1DNYMI2eR5aLwQZgy0z8fuW1tnEbzg5p/N/GKFmqiIHSV4gfp8+X7Fw5NLm7qMfh4xrcPgQCw==
|
||||
dependencies:
|
||||
"@firebase/app-check" "0.6.3"
|
||||
"@firebase/app-check" "0.6.4"
|
||||
"@firebase/app-check-types" "0.5.0"
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/app-check-interop-types@0.2.0":
|
||||
@@ -256,25 +256,25 @@
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app-check-types/-/app-check-types-0.5.0.tgz#1b02826213d7ce6a1cf773c329b46ea1c67064f4"
|
||||
integrity sha512-uwSUj32Mlubybw7tedRzR24RP8M8JUVR3NPiMk3/Z4bCmgEKTlQBwMXrehDAZ2wF+TsBq0SN1c6ema71U/JPyQ==
|
||||
|
||||
"@firebase/app-check@0.6.3":
|
||||
version "0.6.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app-check/-/app-check-0.6.3.tgz#221060e5e0eac1e20ee724478b61e89ad6e8420a"
|
||||
integrity sha512-T9f9ceFLs7x4D2T6whu5a6j7B3qPuYHiZHZxW6DkMh/FoMmRA4/q/HVyu01i9+LyJJx2Xdo6eCcj6ofs9YZjqA==
|
||||
"@firebase/app-check@0.6.4":
|
||||
version "0.6.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app-check/-/app-check-0.6.4.tgz#cb2f7b23f80126800a5632c1d766635266e1b2ff"
|
||||
integrity sha512-M9qyVTWkEkHXmgwGtObvXQqKcOe9iKAOPqm0pCe74mzgKVTNq157ff39+fxHPb4nFbipToY+GuvtabLUzkHehQ==
|
||||
dependencies:
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/app-compat@0.2.3":
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app-compat/-/app-compat-0.2.3.tgz#a31c823d415c041591ee8c355776cd5bca7ef6e2"
|
||||
integrity sha512-sX6rD1KFX6K2CuCnQvc9jZLOgAFZ+sv2jKKahIl4SbTM561D682B8n4Jtx/SgDrvcTVTdb05g4NhZOws9hxYxA==
|
||||
"@firebase/app-compat@0.2.4":
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app-compat/-/app-compat-0.2.4.tgz#610bf28a655373e6b4cda2115fb594f3c576d7d5"
|
||||
integrity sha512-eYKtxMrzi+icZ6dFeJEoEpxu3aq1jp2PeL5vPIOAavJpdgRWFmSGmw3a46Hkay+GGGX4fkJG3vCfuoQsf5ksjA==
|
||||
dependencies:
|
||||
"@firebase/app" "0.9.3"
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/app" "0.9.4"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/app-types@0.9.0":
|
||||
@@ -282,26 +282,26 @@
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.9.0.tgz#35b5c568341e9e263b29b3d2ba0e9cfc9ec7f01e"
|
||||
integrity sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q==
|
||||
|
||||
"@firebase/app@0.9.3":
|
||||
version "0.9.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app/-/app-0.9.3.tgz#6a9c9b2544fa9a50ad8f405355896c54339c228b"
|
||||
integrity sha512-G79JUceVDaHRZ4WkA11GyVldVXhdyRJRwWVQFFvAAVfQJLvy2TA6lQjeUn28F6FmeUWxDGwPC30bxCRWq7Op8Q==
|
||||
"@firebase/app@0.9.4":
|
||||
version "0.9.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app/-/app-0.9.4.tgz#28eb5cd0406f92825afb32a53194d59c19cddb7b"
|
||||
integrity sha512-xX8I6pNqUxhxhaghy9fbjOWOP9ndx5UeN5F0V/PWD2u7xRg88YkzZrDocTAIU17y82UPZ1x1E5n15CsXGcxaOg==
|
||||
dependencies:
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/util" "1.9.3"
|
||||
idb "7.0.1"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/auth-compat@0.3.3":
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/auth-compat/-/auth-compat-0.3.3.tgz#e52f654e3f14b81cecb2fe252e564778fbba0a47"
|
||||
integrity sha512-9asUuGtkzUVELH3LYXdiom1nVVV9bqEPqzHohanoofHL/oVTNcHZ4AQ5CXjNATfb6c1WH32U+nEuPiYg26UUIw==
|
||||
"@firebase/auth-compat@0.3.4":
|
||||
version "0.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/auth-compat/-/auth-compat-0.3.4.tgz#3c00b391876d6192e35eaf805adda3aef43199a5"
|
||||
integrity sha512-AVNZ4pwLV063ngPKU+8tykQ6v+fRlKfBWEp1W+JU1pEJI+GK0thOPrCn22lWyI8LYiDrh3MLIiBJCv7fsyQajw==
|
||||
dependencies:
|
||||
"@firebase/auth" "0.21.3"
|
||||
"@firebase/auth" "0.21.4"
|
||||
"@firebase/auth-types" "0.12.0"
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/util" "1.9.3"
|
||||
node-fetch "2.6.7"
|
||||
tslib "^2.1.0"
|
||||
|
||||
@@ -315,14 +315,14 @@
|
||||
resolved "https://registry.yarnpkg.com/@firebase/auth-types/-/auth-types-0.12.0.tgz#f28e1b68ac3b208ad02a15854c585be6da3e8e79"
|
||||
integrity sha512-pPwaZt+SPOshK8xNoiQlK5XIrS97kFYc3Rc7xmy373QsOJ9MmqXxLaYssP5Kcds4wd2qK//amx/c+A8O2fVeZA==
|
||||
|
||||
"@firebase/auth@0.21.3":
|
||||
version "0.21.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/auth/-/auth-0.21.3.tgz#277a3bf4b09db1b5dd471970cecd844d1835dcbf"
|
||||
integrity sha512-HPbcwgArLBVTowFcn4qaQr6LCx7BidI9yrQ5MRbQNv4PsgK/3UGpzCYaNPPbvgr9fe+0jNdJO+uC0+dk4xIzCQ==
|
||||
"@firebase/auth@0.21.4":
|
||||
version "0.21.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/auth/-/auth-0.21.4.tgz#2ce8a34a78b53a168152b987b7bbd844f0431669"
|
||||
integrity sha512-yZrs1F8sTt8IMCJl29gaxokDZSLjO08r2bL2PNKV1Duz2vJ67ZtVcgHAidyf8BFak9uS8mepd9KlYFDfwUO60Q==
|
||||
dependencies:
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/util" "1.9.3"
|
||||
node-fetch "2.6.7"
|
||||
tslib "^2.1.0"
|
||||
|
||||
@@ -334,7 +334,27 @@
|
||||
"@firebase/util" "1.9.2"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/database-compat@0.3.3", "@firebase/database-compat@^0.3.0":
|
||||
"@firebase/component@0.6.4":
|
||||
version "0.6.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/component/-/component-0.6.4.tgz#8981a6818bd730a7554aa5e0516ffc9b1ae3f33d"
|
||||
integrity sha512-rLMyrXuO9jcAUCaQXCMjCMUsWrba5fzHlNK24xz5j2W6A/SRmK8mZJ/hn7V0fViLbxC0lPMtrK1eYzk6Fg03jA==
|
||||
dependencies:
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/database-compat@0.3.4":
|
||||
version "0.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/database-compat/-/database-compat-0.3.4.tgz#4e57932f7a5ba761cd5ac946ab6b6ab3f660522c"
|
||||
integrity sha512-kuAW+l+sLMUKBThnvxvUZ+Q1ZrF/vFJ58iUY9kAcbX48U03nVzIF6Tmkf0p3WVQwMqiXguSgtOPIB6ZCeF+5Gg==
|
||||
dependencies:
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/database" "0.14.4"
|
||||
"@firebase/database-types" "0.10.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/database-compat@^0.3.0":
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/database-compat/-/database-compat-0.3.3.tgz#4668e32527f57c1dde6cb03f5fde81eb04503ad4"
|
||||
integrity sha512-r+L9jTbvsnb7sD+xz6UKU39DgBWqB2pyjzPNdBeriGC9Ssa2MAZe0bIqjCQg51RRXYc/aa/zK1Q2/4uesZeVgQ==
|
||||
@@ -354,6 +374,14 @@
|
||||
"@firebase/app-types" "0.9.0"
|
||||
"@firebase/util" "1.9.2"
|
||||
|
||||
"@firebase/database-types@0.10.4":
|
||||
version "0.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-0.10.4.tgz#47ba81113512dab637abace61cfb65f63d645ca7"
|
||||
integrity sha512-dPySn0vJ/89ZeBac70T+2tWWPiJXWbmRygYv0smT5TfE3hDrQ09eKMF3Y+vMlTdrMWq7mUdYW5REWPSGH4kAZQ==
|
||||
dependencies:
|
||||
"@firebase/app-types" "0.9.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
|
||||
"@firebase/database@0.14.3":
|
||||
version "0.14.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/database/-/database-0.14.3.tgz#0ddd92e5eeef2dbebefd55ce78b39472a57dd5d3"
|
||||
@@ -366,15 +394,27 @@
|
||||
faye-websocket "0.11.4"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/firestore-compat@0.3.3":
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/firestore-compat/-/firestore-compat-0.3.3.tgz#2fedc13e6242aa98a78cfb710242721d9822c1da"
|
||||
integrity sha512-fMTsSC0s2cF5w2+JoB0dWD/o4kXtLrUCPGnZPuz4S0bqTN2t0vHr3gdAsQLtnadgwB78ACtinYmf4Udwx7TzDg==
|
||||
"@firebase/database@0.14.4":
|
||||
version "0.14.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/database/-/database-0.14.4.tgz#9e7435a16a540ddfdeb5d99d45618e6ede179aa6"
|
||||
integrity sha512-+Ea/IKGwh42jwdjCyzTmeZeLM3oy1h0mFPsTy6OqCWzcu/KFqRAr5Tt1HRCOBlNOdbh84JPZC47WLU18n2VbxQ==
|
||||
dependencies:
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/firestore" "3.8.3"
|
||||
"@firebase/auth-interop-types" "0.2.1"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
faye-websocket "0.11.4"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/firestore-compat@0.3.4":
|
||||
version "0.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/firestore-compat/-/firestore-compat-0.3.4.tgz#1c656c225a1ed2a3cd6af1f4118701b5539a4c44"
|
||||
integrity sha512-xUzz1V53vA1R8S5QQbQ33zqNv0bV+dZpeQKqMXt6HNWa1yiX7lUooGYRws825F+QBOadW1teav1ttXnGZAsgUw==
|
||||
dependencies:
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/firestore" "3.8.4"
|
||||
"@firebase/firestore-types" "2.5.1"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/firestore-types@2.5.1":
|
||||
@@ -382,29 +422,29 @@
|
||||
resolved "https://registry.yarnpkg.com/@firebase/firestore-types/-/firestore-types-2.5.1.tgz#464b2ee057956599ca34de50eae957c30fdbabb7"
|
||||
integrity sha512-xG0CA6EMfYo8YeUxC8FeDzf6W3FX1cLlcAGBYV6Cku12sZRI81oWcu61RSKM66K6kUENP+78Qm8mvroBcm1whw==
|
||||
|
||||
"@firebase/firestore@3.8.3":
|
||||
version "3.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/firestore/-/firestore-3.8.3.tgz#8305113b9535747f982b585b0dd72e85122b5b89"
|
||||
integrity sha512-4xR3Mqj95bxHg3hZnz0O+LQrHkjq+siT2y+B9da6u68qJ8bzzT42JaFgd1vifhbBpVbBzpFaS2RuCq2E+kGv9g==
|
||||
"@firebase/firestore@3.8.4":
|
||||
version "3.8.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/firestore/-/firestore-3.8.4.tgz#66b057330a22f0cd240b60746f2b2920b10dee31"
|
||||
integrity sha512-sNLT4vGBSrx75Q2yLzCHL/1LDS7+UG8gaIohox/GpKYGxt4r8/AsUOmjN4llDqdnFSgY5ePYp2+nHArFXHyZjA==
|
||||
dependencies:
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/util" "1.9.3"
|
||||
"@firebase/webchannel-wrapper" "0.9.0"
|
||||
"@grpc/grpc-js" "~1.7.0"
|
||||
"@grpc/proto-loader" "^0.6.13"
|
||||
node-fetch "2.6.7"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/functions-compat@0.3.3":
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/functions-compat/-/functions-compat-0.3.3.tgz#530c30b4dfea14e71657f780d2c281e16209aed7"
|
||||
integrity sha512-UIAJ2gzNq0p/61cXqkpi9DnlQt0hdlGqgmL5an7KuJth2Iv5uGpKg/+OapAZxPuiUNZgTEyZDB7kNBHvnxWq5w==
|
||||
"@firebase/functions-compat@0.3.4":
|
||||
version "0.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/functions-compat/-/functions-compat-0.3.4.tgz#2b37321d893e816fec80435bb7cbca90f293bc0d"
|
||||
integrity sha512-kxVxTGyLV1MBR3sp3mI+eQ6JBqz0G5bk310F8eX4HzDFk4xjk5xY0KdHktMH+edM2xs1BOg0vwvvsAHczIjB+w==
|
||||
dependencies:
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/functions" "0.9.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/functions" "0.9.4"
|
||||
"@firebase/functions-types" "0.6.0"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/functions-types@0.6.0":
|
||||
@@ -412,28 +452,28 @@
|
||||
resolved "https://registry.yarnpkg.com/@firebase/functions-types/-/functions-types-0.6.0.tgz#ccd7000dc6fc668f5acb4e6a6a042a877a555ef2"
|
||||
integrity sha512-hfEw5VJtgWXIRf92ImLkgENqpL6IWpYaXVYiRkFY1jJ9+6tIhWM7IzzwbevwIIud/jaxKVdRzD7QBWfPmkwCYw==
|
||||
|
||||
"@firebase/functions@0.9.3":
|
||||
version "0.9.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/functions/-/functions-0.9.3.tgz#9ef33efcd38b0235e84ae472d9b51597efe3f871"
|
||||
integrity sha512-tPJgYY2ROQSYuzvgxZRoHeDj+Ic07/bWHwaftgTriawtupmFOkt5iikuhJSJUhaOpFh9TB335OvCXJw1N+BIlQ==
|
||||
"@firebase/functions@0.9.4":
|
||||
version "0.9.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/functions/-/functions-0.9.4.tgz#47232500be6847f1c7d3fa74eb36f621bd01a160"
|
||||
integrity sha512-3H2qh6U+q+nepO5Hds+Ddl6J0pS+zisuBLqqQMRBHv9XpWfu0PnDHklNmE8rZ+ccTEXvBj6zjkPfdxt6NisvlQ==
|
||||
dependencies:
|
||||
"@firebase/app-check-interop-types" "0.2.0"
|
||||
"@firebase/auth-interop-types" "0.2.1"
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/messaging-interop-types" "0.2.0"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/util" "1.9.3"
|
||||
node-fetch "2.6.7"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/installations-compat@0.2.3":
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/installations-compat/-/installations-compat-0.2.3.tgz#42b05f4e5204c354e0fa059378402bd47635e5bf"
|
||||
integrity sha512-K9rKM/ym06lkpaKz7bMLxzHK/HEk65XfLJBV+dJkIuWeO0EqqC9VFGrpWAo0QmgC4BqbU58T6VBbzoJjb0gaFw==
|
||||
"@firebase/installations-compat@0.2.4":
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/installations-compat/-/installations-compat-0.2.4.tgz#b5557c897b4cd3635a59887a8bf69c3731aaa952"
|
||||
integrity sha512-LI9dYjp0aT9Njkn9U4JRrDqQ6KXeAmFbRC0E7jI7+hxl5YmRWysq5qgQl22hcWpTk+cm3es66d/apoDU/A9n6Q==
|
||||
dependencies:
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/installations" "0.6.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/installations" "0.6.4"
|
||||
"@firebase/installations-types" "0.5.0"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/installations-types@0.5.0":
|
||||
@@ -441,13 +481,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@firebase/installations-types/-/installations-types-0.5.0.tgz#2adad64755cd33648519b573ec7ec30f21fb5354"
|
||||
integrity sha512-9DP+RGfzoI2jH7gY4SlzqvZ+hr7gYzPODrbzVD82Y12kScZ6ZpRg/i3j6rleto8vTFC8n6Len4560FnV1w2IRg==
|
||||
|
||||
"@firebase/installations@0.6.3":
|
||||
version "0.6.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/installations/-/installations-0.6.3.tgz#b833cf12ac63666246a57100dbdd669fb76a23aa"
|
||||
integrity sha512-20JFWm+tweNoRjRbz8/Y4I7O5pUJGZsFKCkLl1qNxfNYECSfrZUuozIDJDZC/MeVn5+kB9CwjThDlgQEPrfLdg==
|
||||
"@firebase/installations@0.6.4":
|
||||
version "0.6.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/installations/-/installations-0.6.4.tgz#20382e33e6062ac5eff4bede8e468ed4c367609e"
|
||||
integrity sha512-u5y88rtsp7NYkCHC3ElbFBrPtieUybZluXyzl7+4BsIz4sqb4vSAuwHEUgCgCeaQhvsnxDEU6icly8U9zsJigA==
|
||||
dependencies:
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/util" "1.9.3"
|
||||
idb "7.0.1"
|
||||
tslib "^2.1.0"
|
||||
|
||||
@@ -458,14 +498,14 @@
|
||||
dependencies:
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/messaging-compat@0.2.3":
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/messaging-compat/-/messaging-compat-0.2.3.tgz#2d222e4078643e49a708b61b6d0e51edc2bc73bd"
|
||||
integrity sha512-MmuuohXV2YRzIoJmDngI5qqO/cF2q7SdAaw7k4r61W3ReJy7x4/rtqrIvwNVhM6X/X8NFGBbsYKsCfRHWjFdkg==
|
||||
"@firebase/messaging-compat@0.2.4":
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/messaging-compat/-/messaging-compat-0.2.4.tgz#323ca48deef77065b4fcda3cfd662c4337dffcfd"
|
||||
integrity sha512-lyFjeUhIsPRYDPNIkYX1LcZMpoVbBWXX4rPl7c/rqc7G+EUea7IEtSt4MxTvh6fDfPuzLn7+FZADfscC+tNMfg==
|
||||
dependencies:
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/messaging" "0.12.3"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/messaging" "0.12.4"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/messaging-interop-types@0.2.0":
|
||||
@@ -473,28 +513,28 @@
|
||||
resolved "https://registry.yarnpkg.com/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.0.tgz#6056f8904a696bf0f7fdcf5f2ca8f008e8f6b064"
|
||||
integrity sha512-ujA8dcRuVeBixGR9CtegfpU4YmZf3Lt7QYkcj693FFannwNuZgfAYaTmbJ40dtjB81SAu6tbFPL9YLNT15KmOQ==
|
||||
|
||||
"@firebase/messaging@0.12.3":
|
||||
version "0.12.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/messaging/-/messaging-0.12.3.tgz#3fd521e31deb9b81ec6316062deb1dcc8198d038"
|
||||
integrity sha512-a3ZKcGDiV2sKmQDB56PpgL1yjFxXCtff2+v1grnAZZ4GnfNQ74t2EHCbmgY7xRX7ThzMqug54oxhuk4ur0MIoA==
|
||||
"@firebase/messaging@0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/messaging/-/messaging-0.12.4.tgz#ccb49df5ab97d5650c9cf5b8c77ddc34daafcfe0"
|
||||
integrity sha512-6JLZct6zUaex4g7HI3QbzeUrg9xcnmDAPTWpkoMpd/GoSVWH98zDoWXMGrcvHeCAIsLpFMe4MPoZkJbrPhaASw==
|
||||
dependencies:
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/installations" "0.6.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/installations" "0.6.4"
|
||||
"@firebase/messaging-interop-types" "0.2.0"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/util" "1.9.3"
|
||||
idb "7.0.1"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/performance-compat@0.2.3":
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/performance-compat/-/performance-compat-0.2.3.tgz#f3939bedc2017a95772fde64a72e97fe4b184268"
|
||||
integrity sha512-I3rqZsIhauXn4iApfj1ttKQdlti/r8OZBG4YK10vxKSdhAzTIDWDKEsdoCXvvKLwplcMv36sM3WPAPGQLqY5MQ==
|
||||
"@firebase/performance-compat@0.2.4":
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/performance-compat/-/performance-compat-0.2.4.tgz#95cbf32057b5d9f0c75d804bc50e6ed3ba486274"
|
||||
integrity sha512-nnHUb8uP9G8islzcld/k6Bg5RhX62VpbAb/Anj7IXs/hp32Eb2LqFPZK4sy3pKkBUO5wcrlRWQa6wKOxqlUqsg==
|
||||
dependencies:
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/performance" "0.6.3"
|
||||
"@firebase/performance" "0.6.4"
|
||||
"@firebase/performance-types" "0.2.0"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/performance-types@0.2.0":
|
||||
@@ -502,27 +542,27 @@
|
||||
resolved "https://registry.yarnpkg.com/@firebase/performance-types/-/performance-types-0.2.0.tgz#400685f7a3455970817136d9b48ce07a4b9562ff"
|
||||
integrity sha512-kYrbr8e/CYr1KLrLYZZt2noNnf+pRwDq2KK9Au9jHrBMnb0/C9X9yWSXmZkFt4UIdsQknBq8uBB7fsybZdOBTA==
|
||||
|
||||
"@firebase/performance@0.6.3":
|
||||
version "0.6.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/performance/-/performance-0.6.3.tgz#663c468dc4d62b6e211938377e21a01854803646"
|
||||
integrity sha512-NQmQN6Ete7i9jz1mzULJZEGvsOmwwdUy6vpqnhUxSFMYPnlBKjX+yypCUUJDDN5zff5+kfwSD1qCyUAaS0xWUA==
|
||||
"@firebase/performance@0.6.4":
|
||||
version "0.6.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/performance/-/performance-0.6.4.tgz#0ad766bfcfab4f386f4fe0bef43bbcf505015069"
|
||||
integrity sha512-HfTn/bd8mfy/61vEqaBelNiNnvAbUtME2S25A67Nb34zVuCSCRIX4SseXY6zBnOFj3oLisaEqhVcJmVPAej67g==
|
||||
dependencies:
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/installations" "0.6.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/installations" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/remote-config-compat@0.2.3":
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/remote-config-compat/-/remote-config-compat-0.2.3.tgz#b0c0ef9978186bc58b262a39b9a41ec1bf819df3"
|
||||
integrity sha512-w/ZL03YgYaXq03xIRyJ5oPhXZi6iDsY/v0J9Y7I7SqxCYytEnHVrL9nvBqd9R94y5LRAVNPCLokJeeizaUz4VQ==
|
||||
"@firebase/remote-config-compat@0.2.4":
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/remote-config-compat/-/remote-config-compat-0.2.4.tgz#1f494c81a6c9560b1f9ca1b4fbd4bbbe47cf4776"
|
||||
integrity sha512-FKiki53jZirrDFkBHglB3C07j5wBpitAaj8kLME6g8Mx+aq7u9P7qfmuSRytiOItADhWUj7O1JIv7n9q87SuwA==
|
||||
dependencies:
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/remote-config" "0.4.3"
|
||||
"@firebase/remote-config" "0.4.4"
|
||||
"@firebase/remote-config-types" "0.3.0"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/remote-config-types@0.3.0":
|
||||
@@ -530,26 +570,26 @@
|
||||
resolved "https://registry.yarnpkg.com/@firebase/remote-config-types/-/remote-config-types-0.3.0.tgz#689900dcdb3e5c059e8499b29db393e4e51314b4"
|
||||
integrity sha512-RtEH4vdcbXZuZWRZbIRmQVBNsE7VDQpet2qFvq6vwKLBIQRQR5Kh58M4ok3A3US8Sr3rubYnaGqZSurCwI8uMA==
|
||||
|
||||
"@firebase/remote-config@0.4.3":
|
||||
version "0.4.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/remote-config/-/remote-config-0.4.3.tgz#85c4934d093a4c7b8a336af70ada83e936347a2b"
|
||||
integrity sha512-Q6d4jBWZoNt6SYq87bjtDGUHFkKwAmGnNjWyRjl14AZqE1ilgd9NZHmutharlYJ3LvxMsid80HdK5SgGEpIPfg==
|
||||
"@firebase/remote-config@0.4.4":
|
||||
version "0.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/remote-config/-/remote-config-0.4.4.tgz#6a496117054de58744bc9f382d2a6d1e14060c65"
|
||||
integrity sha512-x1ioTHGX8ZwDSTOVp8PBLv2/wfwKzb4pxi0gFezS5GCJwbLlloUH4YYZHHS83IPxnua8b6l0IXUaWd0RgbWwzQ==
|
||||
dependencies:
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/installations" "0.6.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/installations" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/storage-compat@0.3.1":
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/storage-compat/-/storage-compat-0.3.1.tgz#b8536c3a435f8ce5eb07796ca10fda16896a9bae"
|
||||
integrity sha512-6HaTvWsT5Yy3j4UpCZpMcFUYEkJ2XYWukdyTl02u6VjSBRLvkhOXPzEfMvgVWqhnF/rYVfPdjrZ904wk5OxtmQ==
|
||||
"@firebase/storage-compat@0.3.2":
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/storage-compat/-/storage-compat-0.3.2.tgz#51a97170fd652a516f729f82b97af369e5a2f8d7"
|
||||
integrity sha512-wvsXlLa9DVOMQJckbDNhXKKxRNNewyUhhbXev3t8kSgoCotd1v3MmqhKKz93ePhDnhHnDs7bYHy+Qa8dRY6BXw==
|
||||
dependencies:
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/storage" "0.11.1"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/storage" "0.11.2"
|
||||
"@firebase/storage-types" "0.8.0"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/storage-types@0.8.0":
|
||||
@@ -557,13 +597,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@firebase/storage-types/-/storage-types-0.8.0.tgz#f1e40a5361d59240b6e84fac7fbbbb622bfaf707"
|
||||
integrity sha512-isRHcGrTs9kITJC0AVehHfpraWFui39MPaU7Eo8QfWlqW7YPymBmRgjDrlOgFdURh6Cdeg07zmkLP5tzTKRSpg==
|
||||
|
||||
"@firebase/storage@0.11.1":
|
||||
version "0.11.1"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/storage/-/storage-0.11.1.tgz#602ddb7bce77077800a46bcdfa76f36d7a265c51"
|
||||
integrity sha512-Xv8EG2j52ugF2xayBz26U9J0VBXHXPMVxSN+ph3R3BSoHxvMLaPu+qUYKHavSt+zbcgPH2GyBhrCdJK6SaDFPA==
|
||||
"@firebase/storage@0.11.2":
|
||||
version "0.11.2"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/storage/-/storage-0.11.2.tgz#c5e0316543fe1c4026b8e3910f85ad73f5b77571"
|
||||
integrity sha512-CtvoFaBI4hGXlXbaCHf8humajkbXhs39Nbh6MbNxtwJiCqxPy9iH3D3CCfXAvP0QvAAwmJUTK3+z9a++Kc4nkA==
|
||||
dependencies:
|
||||
"@firebase/component" "0.6.3"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/util" "1.9.3"
|
||||
node-fetch "2.6.7"
|
||||
tslib "^2.1.0"
|
||||
|
||||
@@ -574,6 +614,13 @@
|
||||
dependencies:
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/util@1.9.3":
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/util/-/util-1.9.3.tgz#45458dd5cd02d90e55c656e84adf6f3decf4b7ed"
|
||||
integrity sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==
|
||||
dependencies:
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/webchannel-wrapper@0.9.0":
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.9.0.tgz#9340bce56560a8bdba1d25d6281d4bfc397450dc"
|
||||
@@ -679,9 +726,9 @@
|
||||
yargs "^16.2.0"
|
||||
|
||||
"@headlessui/react@^1.7.11":
|
||||
version "1.7.12"
|
||||
resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.7.12.tgz#9ab2baa3c4f632782631e00937f9531a34033619"
|
||||
integrity sha512-FhSx5V+Qp0GvbTpaxyS+ymGDDNntCacClWsk/d8Upbr19g3AsPbjfPk4+m2CgJGcuCB5Dz7LpUIOAbvQTyjL2g==
|
||||
version "1.7.13"
|
||||
resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.7.13.tgz#fd150b394954e9f1d86ed2340cffd1217d6e7628"
|
||||
integrity sha512-9n+EQKRtD9266xIHXdY5MfiXPDfYwl7zBM7KOx2Ae3Gdgxy8QML1FkCMjq6AsOf0l6N9uvI4HcFtuFlenaldKg==
|
||||
dependencies:
|
||||
client-only "^0.0.1"
|
||||
|
||||
@@ -737,10 +784,10 @@
|
||||
dependencies:
|
||||
glob "7.1.7"
|
||||
|
||||
"@next/font@13.2.0":
|
||||
version "13.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/font/-/font-13.2.0.tgz#677b3fc67243bccbae94d7d1e96a494be98206c4"
|
||||
integrity sha512-pWoegIxqegV+9+gFmRCZao6xhA2m3kKS34lMXqShJ5ibRuyHkP/tfDE82LzYZmVQ3p51ZrkwTugNwy/ohiE2cA==
|
||||
"@next/font@13.2.3":
|
||||
version "13.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@next/font/-/font-13.2.3.tgz#96d8a1b431425b47e01f3620118d570e2148e312"
|
||||
integrity sha512-7EHzk0f7FVYICLUZTpyPk93IfcTUao++Xt1Sgb+Zk5dVOCYHabqLtlF5ywSoXIqyFlo0qlshEBxsrzHAGTWkDw==
|
||||
|
||||
"@next/swc-android-arm-eabi@13.2.3":
|
||||
version "13.2.3"
|
||||
@@ -1048,15 +1095,15 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca"
|
||||
integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==
|
||||
|
||||
"@types/node@*", "@types/node@>=12.12.47", "@types/node@>=13.7.0":
|
||||
"@types/node@*":
|
||||
version "18.14.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.14.4.tgz#0e64ec0b35a772e1e3d849f9a0ff61782d0cb647"
|
||||
integrity sha512-VhCw7I7qO2X49+jaKcAUwi3rR+hbxT5VcYF493+Z5kMLI0DL568b7JI4IDJaxWFH0D/xwmGJNoXisyX+w7GH/g==
|
||||
|
||||
"@types/node@18.14.2":
|
||||
version "18.14.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.14.2.tgz#c076ed1d7b6095078ad3cf21dfeea951842778b1"
|
||||
integrity sha512-1uEQxww3DaghA0RxqHx0O0ppVlo43pJhepY51OxuQIKHpjbnYLA7vcdwioNPzIqmC2u3I/dmylcqjlh0e7AyUA==
|
||||
"@types/node@18.14.6", "@types/node@>=12.12.47", "@types/node@>=13.7.0":
|
||||
version "18.14.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.14.6.tgz#ae1973dd2b1eeb1825695bb11ebfb746d27e3e93"
|
||||
integrity sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA==
|
||||
|
||||
"@types/parse-json@^4.0.0":
|
||||
version "4.0.0"
|
||||
@@ -2572,36 +2619,36 @@ firebase-functions@^4.2.1:
|
||||
node-fetch "^2.6.7"
|
||||
|
||||
firebase@^9.17.1:
|
||||
version "9.17.1"
|
||||
resolved "https://registry.yarnpkg.com/firebase/-/firebase-9.17.1.tgz#91c56fe9d9bf5ed1c405030e4fe8133c6069fd40"
|
||||
integrity sha512-MSZaTRaaRLgDFLqoEnoPYK8zkLwQNvYeLZ3YSKdcQxG8hDifNO22ywS1cSA1ZCGHlQeOsDtfDwBejKcANf/RQw==
|
||||
version "9.17.2"
|
||||
resolved "https://registry.yarnpkg.com/firebase/-/firebase-9.17.2.tgz#950720666b1628a0b16926fbea4fc4217bd66185"
|
||||
integrity sha512-2V95/evwB3zsi6RYHCvPXfkiQrSepFQJohv3YGoQVhS0bvXuYXmkLtrCVGShxneB/5t9HE5C9q9C8XPnK4APBw==
|
||||
dependencies:
|
||||
"@firebase/analytics" "0.9.3"
|
||||
"@firebase/analytics-compat" "0.2.3"
|
||||
"@firebase/app" "0.9.3"
|
||||
"@firebase/app-check" "0.6.3"
|
||||
"@firebase/app-check-compat" "0.3.3"
|
||||
"@firebase/app-compat" "0.2.3"
|
||||
"@firebase/analytics" "0.9.4"
|
||||
"@firebase/analytics-compat" "0.2.4"
|
||||
"@firebase/app" "0.9.4"
|
||||
"@firebase/app-check" "0.6.4"
|
||||
"@firebase/app-check-compat" "0.3.4"
|
||||
"@firebase/app-compat" "0.2.4"
|
||||
"@firebase/app-types" "0.9.0"
|
||||
"@firebase/auth" "0.21.3"
|
||||
"@firebase/auth-compat" "0.3.3"
|
||||
"@firebase/database" "0.14.3"
|
||||
"@firebase/database-compat" "0.3.3"
|
||||
"@firebase/firestore" "3.8.3"
|
||||
"@firebase/firestore-compat" "0.3.3"
|
||||
"@firebase/functions" "0.9.3"
|
||||
"@firebase/functions-compat" "0.3.3"
|
||||
"@firebase/installations" "0.6.3"
|
||||
"@firebase/installations-compat" "0.2.3"
|
||||
"@firebase/messaging" "0.12.3"
|
||||
"@firebase/messaging-compat" "0.2.3"
|
||||
"@firebase/performance" "0.6.3"
|
||||
"@firebase/performance-compat" "0.2.3"
|
||||
"@firebase/remote-config" "0.4.3"
|
||||
"@firebase/remote-config-compat" "0.2.3"
|
||||
"@firebase/storage" "0.11.1"
|
||||
"@firebase/storage-compat" "0.3.1"
|
||||
"@firebase/util" "1.9.2"
|
||||
"@firebase/auth" "0.21.4"
|
||||
"@firebase/auth-compat" "0.3.4"
|
||||
"@firebase/database" "0.14.4"
|
||||
"@firebase/database-compat" "0.3.4"
|
||||
"@firebase/firestore" "3.8.4"
|
||||
"@firebase/firestore-compat" "0.3.4"
|
||||
"@firebase/functions" "0.9.4"
|
||||
"@firebase/functions-compat" "0.3.4"
|
||||
"@firebase/installations" "0.6.4"
|
||||
"@firebase/installations-compat" "0.2.4"
|
||||
"@firebase/messaging" "0.12.4"
|
||||
"@firebase/messaging-compat" "0.2.4"
|
||||
"@firebase/performance" "0.6.4"
|
||||
"@firebase/performance-compat" "0.2.4"
|
||||
"@firebase/remote-config" "0.4.4"
|
||||
"@firebase/remote-config-compat" "0.2.4"
|
||||
"@firebase/storage" "0.11.2"
|
||||
"@firebase/storage-compat" "0.3.2"
|
||||
"@firebase/util" "1.9.3"
|
||||
|
||||
fireschema@^4.0.4:
|
||||
version "4.0.4"
|
||||
@@ -2903,10 +2950,10 @@ googleapis-common@^6.0.0:
|
||||
url-template "^2.0.8"
|
||||
uuid "^9.0.0"
|
||||
|
||||
googleapis@111.0.0:
|
||||
version "111.0.0"
|
||||
resolved "https://registry.yarnpkg.com/googleapis/-/googleapis-111.0.0.tgz#aa3daac5ab033085d25fe8c52527ff35b2f7f688"
|
||||
integrity sha512-nIIH+J/o/xjIscJcv3H3BCYgsFiI5ziM3Nbh2lHOWglYGqXE0Nqdt2lfCt4hX257QHEyC1y1iODDkmAMPWDYlw==
|
||||
googleapis@112.0.0:
|
||||
version "112.0.0"
|
||||
resolved "https://registry.yarnpkg.com/googleapis/-/googleapis-112.0.0.tgz#e957811a1df3c408f934c0047e091d5d8f14b7ef"
|
||||
integrity sha512-WPfXhYZVrbbJRxB+ZZDksjuelmt49Mcl/1mo7w05kvLS1EbynvTELsNTJwh+hNrjsFKdh4izWLAcjTDo0Boycg==
|
||||
dependencies:
|
||||
google-auth-library "^8.0.2"
|
||||
googleapis-common "^6.0.0"
|
||||
@@ -4355,9 +4402,9 @@ react-firebase-hooks@^3.0.3:
|
||||
integrity sha512-9LztZGaZU0qJY/TQWzkBlfVrFmu0Ui6HE8CUjU7tNz9oGKGx5tUQG/xQbfyMIGClErgnnQsm8sC+oU9pg8Ri5Q==
|
||||
|
||||
react-hook-form@^7.43.2:
|
||||
version "7.43.3"
|
||||
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.43.3.tgz#780af64ea1f3c5864626a377e302bfcc7750af6f"
|
||||
integrity sha512-LV6Fixh+hirrl6dXbM78aB6n//82aKbsNbcofF3wc6nx1UJLu3Jj/gsg1E5C9iISnLX+du8VTUyBUz2aCy+H7w==
|
||||
version "7.43.4"
|
||||
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.43.4.tgz#32c12cce916e2ba50178148a5ef5acffeaae2a3e"
|
||||
integrity sha512-JZp05wvmuV8qr3NNDWwyhiQL05sh9E8x/2NoWtkdiyyiezmwOr5pKexlvbCEfBMa7ZYrvzk88G/uhLl47T9b7Q==
|
||||
|
||||
react-hot-toast@^2.4.0:
|
||||
version "2.4.0"
|
||||
@@ -4367,9 +4414,9 @@ react-hot-toast@^2.4.0:
|
||||
goober "^2.1.10"
|
||||
|
||||
react-icons@^4.7.1:
|
||||
version "4.7.1"
|
||||
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.7.1.tgz#0f4b25a5694e6972677cb189d2a72eabea7a8345"
|
||||
integrity sha512-yHd3oKGMgm7zxo3EA7H2n7vxSoiGmHk5t6Ou4bXsfcgWyhfDKMpyKfhHR6Bjnn63c+YXBLBPUql9H4wPJM6sXw==
|
||||
version "4.8.0"
|
||||
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.8.0.tgz#621e900caa23b912f737e41be57f27f6b2bff445"
|
||||
integrity sha512-N6+kOLcihDiAnj5Czu637waJqSnwlMNROzVZMhfX68V/9bu9qHaMIJC4UdozWoOk57gahFCNHwVvWzm0MTzRjg==
|
||||
|
||||
react-is@^16.13.1, react-is@^16.7.0:
|
||||
version "16.13.1"
|
||||
@@ -4891,9 +4938,9 @@ text-table@^0.2.0:
|
||||
integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
|
||||
|
||||
theme-change@^2.3.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/theme-change/-/theme-change-2.4.0.tgz#db9e7fded16a2fcd5555e19fa3755ef9ff4996da"
|
||||
integrity sha512-HbMckoxM7sV8L7wk53S5ceiBQWcTxFozuvUmvjdjPqpyVFkzPQHylSsDHYyT8qTruORe+1Sft7ExqlXQEeWHBA==
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/theme-change/-/theme-change-2.5.0.tgz#d3b064af9c4cd01ab16ce0a4ecb251c827a50e68"
|
||||
integrity sha512-B/UdsgdHAGhSKHTAQnxg/etN0RaMDpehuJmZIjLMDVJ6DGIliRHGD6pODi1CXLQAN9GV0GSyB3G6yCuK05PkPQ==
|
||||
|
||||
thread-stream@^0.15.1:
|
||||
version "0.15.2"
|
||||
@@ -5287,6 +5334,6 @@ yocto-queue@^0.1.0:
|
||||
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
||||
|
||||
zod@^3.20.6:
|
||||
version "3.20.6"
|
||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.20.6.tgz#2f2f08ff81291d47d99e86140fedb4e0db08361a"
|
||||
integrity sha512-oyu0m54SGCtzh6EClBVqDDlAYRz4jrVtKwQ7ZnsEmMI9HnzuZFj8QFwAY1M5uniIYACdGvv0PBWPF2kO0aNofA==
|
||||
version "3.21.1"
|
||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.21.1.tgz#ac5bb7cf68876281ebd02f95ac4bb9a080370282"
|
||||
integrity sha512-+dTu2m6gmCbO9Ahm4ZBDapx2O6ZY9QSPXst2WXjcznPMwf2YNpn3RevLx4KkZp1OPW/ouFcoBtBzFz/LeY69oA==
|
||||
|
||||
Reference in New Issue
Block a user