Skip to content

Commit

Permalink
feat: remove resend button
Browse files Browse the repository at this point in the history
  • Loading branch information
Jadapema committed Jan 20, 2025
1 parent dc82897 commit 716cc8f
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 33 deletions.
5 changes: 3 additions & 2 deletions src/config-global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ export const GLOBAL_CONSTANTS = {
EMAIL_API_KEY: process.env.VITE_EMAILJS_PUBLIC_KEY || import.meta.env.VITE_EMAILJS_PUBLIC_KEY || '',
EMAIL_SERVICE_ID: process.env.VITE_EMAILJS_SERVICE_ID || import.meta.env.VITE_EMAILJS_SERVICE_ID || '',
EMAIL_TEMPLATE_ID: process.env.VITE_EMAILJS_TEMPLATE_ID || import.meta.env.VITE_EMAILJS_TEMPLATE_ID || '',
BASE_URL: 'https://app.watchit.movie',
LOGO_URL: 'https://app.watchit.movie',
SENDER_EMAIL: process.env.VITE_SENDER_EMAIL || import.meta.env.VITE_SENDER_EMAIL || '',
BASE_URL: process.env.VITE_BASE_URL || import.meta.env.VITE_BASE_URL || '',
LOGO_URL: process.env.VITE_LOGO_URL || import.meta.env.VITE_LOGO_URL || '',
};

export const MAPBOX_API = import.meta.env.VITE_MAPBOX_API || '';
Expand Down
65 changes: 61 additions & 4 deletions src/hooks/use-referrals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,30 @@ export interface Invitation {

export type EmailParams = {
to_email: string;
from_email: string;
from_name: string;
};

const useReferrals = () => {
/**
* State variables to manage invitations, loading state, and error messages.
*/
const [invitations, setInvitations] = useState<Invitation[]>([]);
const [loading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<string | null>(null);

/**
* Retrieve the current user's email and session data from Redux (or your global state).
* Adjust according to how you store user data in your application.
*/
const userEmail = useSelector((state: any) => state.auth.email);
const sessionData = useSelector((state: any) => state.auth.session);

/**
* Fetches all invitations from the Supabase 'invitations' table filtered by senderId.
* This could be used, for example, to list all invitations sent by the current user.
*
* @param {string} senderId - The ID of the user who sent the invitations.
*/
const fetchInvitations = async (senderId: string) => {
setLoading(true);
setError(null);
Expand All @@ -52,6 +64,11 @@ const useReferrals = () => {
setLoading(false);
};

/**
* Checks whether the current user's email has a pending invitation in the 'invitations' table.
*
* @returns {Promise<boolean>} - Returns true if there is at least one pending invitation for the current user's email, otherwise false.
*/
const checkIfMyEmailHasPendingInvite = async (): Promise<boolean> => {
setLoading(true);
setError(null);
Expand All @@ -66,6 +83,13 @@ const useReferrals = () => {
return hasPending;
};

/**
* Accepts an existing invitation by updating its status from 'pending' to 'accepted'.
* and set the `receiver_id` to the current user's profile ID.
*
* @param {string} invitationId - The ID of the invitation to accept.
* @returns {Promise<Invitation | null>} - Returns the updated invitation if successful, otherwise null.
*/
const acceptInvitation = async (invitationId: string): Promise<Invitation | null> => {
setLoading(true);
setError(null);
Expand Down Expand Up @@ -94,6 +118,12 @@ const useReferrals = () => {
return data;
};

/**
* Checks if there is already an invitation from the current user (userEmail) to the given destinationEmail.
*
* @param {string} destinationEmail - The email to check against the 'destination' field in the database.
* @returns {Promise<boolean>} - Returns true if there is an existing invitation, false otherwise.
*/
const checkIfInvitationSent = async (destinationEmail: string): Promise<boolean> => {
setLoading(true);
setError(null);
Expand All @@ -108,6 +138,13 @@ const useReferrals = () => {
return exists;
};

/**
* Checks if the specified email already has an accepted invitation.
* This is useful to see if the user is already enrolled/registered via invitation.
*
* @param {string} destinationEmail - The email to check.
* @returns {Promise<boolean>} - Returns true if there's an invitation with status 'accepted' for this email, otherwise false.
*/
const checkIfEmailAlreadyAccepted = async (destinationEmail: string): Promise<boolean> => {
setLoading(true);
setError(null);
Expand All @@ -122,6 +159,14 @@ const useReferrals = () => {
return accepted;
};

/**
* Sends a new invitation. Inserts a record into the 'invitations' table in Supabase,
* and then triggers an email using EmailJS.
*
* @param {string} destination - The email address of the invitee.
* @param {any} payload - Additional data you want to attach to the invitation (e.g., sender's profile info).
* @returns {Promise<void>} - Throws an error if something goes wrong.
*/
const sendInvitation = async (destination: string, payload: any): Promise<void> => {
const { error } = await sendInvitationAction(destination, payload, userEmail, sessionData);

Expand All @@ -131,14 +176,23 @@ const useReferrals = () => {
} else {
console.log('Invitation stored successfully in Supabase.');

// Send the email using EmailJS
await sendEmail({
to_email: destination,
from_email: userEmail ?? '[email protected]',
from_name: payload?.data?.from?.displayName ?? 'Watchit Web3xAI',
});
}
};

/**
* ------------------------------------------------------------------
* Accept or Create an 'accepted' invitation for a given userEmail.
*
* 1) If there's any 'pending' invitation with destination = userEmail,
* accept the first one found.
* 2) Otherwise, create a new invitation record with status = 'accepted'.
* ------------------------------------------------------------------
*/
const acceptOrCreateInvitationForUser = async () => {
const { error } = await acceptOrCreateInvitationForUserAction(userEmail, sessionData);

Expand All @@ -148,12 +202,12 @@ const useReferrals = () => {
};

const sendEmail = async (data: EmailParams) => {
const { from_name, from_email, to_email } = data;
const { from_name, to_email } = data;

const templateParams = {
to_email,
from_name,
from_email,
from_email: GLOBAL_CONSTANTS.SENDER_EMAIL,
};

try {
Expand All @@ -170,6 +224,9 @@ const useReferrals = () => {
}
};

/**
* Return all state variables and methods so they can be used in any component that imports this hook.
*/
return {
// State
invitations,
Expand Down
2 changes: 1 addition & 1 deletion src/sections/user/profile-referrals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ interface ProfileReferralsProps {
const TABLE_HEAD = [
{ id: 'email', label: 'Email'},
{ id: 'status', label: 'Status' },
{ id: 'resend', label: 'Resend' },
{ id: 'profile', label: 'Profile' },
];

const ProfileReferrals : FC<ProfileReferralsProps> = ({ referrals, loading }) => {
Expand Down
39 changes: 13 additions & 26 deletions src/sections/user/view/profile-referrals-table-row.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
// DATE IMPORTS
import { formatDistance } from 'date-fns';

// @MUI
// MUI IMPORTS
import Typography from '@mui/material/Typography';
import TableRow from '@mui/material/TableRow';
import TableCell from '@mui/material/TableCell';
import ListItemText from '@mui/material/ListItemText';

// Project components
import useReferrals, {Invitation} from "@src/hooks/use-referrals.ts";
import Button from "@mui/material/Button";

// LOCAL IMPORTS
import {Invitation} from "@src/hooks/use-referrals.ts";
import AvatarProfile from "@src/components/avatar/avatar.tsx";
import {useRouter} from "@src/routes/hooks";
import {paths} from "@src/routes/paths.ts";
import {useSelector} from "react-redux";
import {notifySuccess} from "@notifications/internal-notifications.ts";
import {SUCCESS} from "@notifications/success.ts";

// ----------------------------------------------------------------------

Expand All @@ -32,24 +30,11 @@ const capitalizeFirstLetter = (string: string) => {

export default function ProfileReferralsTableRow({ row, selected }: Props) {
const { destination, status, created_at: date, id, receiver_id } = row;
const sessionData = useSelector((state: any) => state.auth.session);
const userEmail = useSelector((state: any) => state.auth.email);
const router = useRouter();
const { sendEmail } = useReferrals();

// If receiver_id is null, send again; otherwise, view profile as link
const handleClick = () => {
if (receiver_id === null) {
sendEmail({
from_name: sessionData?.profile?.metadata?.displayName ?? 'Watchit Web3xAI',
to_email: destination,
from_email: userEmail ?? '[email protected]'
}).then((_r) => {
notifySuccess(SUCCESS.INVITATIONS_SUCCESSFULLY);
})
} else {
router.push(paths.dashboard.user.root(receiver_id));
}
receiver_id && router.push(paths.dashboard.user.root(receiver_id));
}

const dateObject = new Date(date);
Expand Down Expand Up @@ -77,11 +62,13 @@ export default function ProfileReferralsTableRow({ row, selected }: Props) {
</TableCell>

<TableCell>
<Button variant="outlined" size="small" onClick={handleClick}>
{
receiver_id === null ? 'Resend' : 'View profile'
}
</Button>
{
receiver_id ? (
<Button variant="outlined" size="small" onClick={handleClick}>
View profile
</Button>
) : <></>
}
</TableCell>
</TableRow>
);
Expand Down

0 comments on commit 716cc8f

Please sign in to comment.