Skip to content

Commit

Permalink
Merge pull request #453 from WatchItDev/next
Browse files Browse the repository at this point in the history
Next
  • Loading branch information
geolffreym authored Jan 21, 2025
2 parents 328ea55 + e5a7f70 commit 0775c58
Show file tree
Hide file tree
Showing 11 changed files with 184 additions and 47 deletions.
14 changes: 11 additions & 3 deletions src/components/avatar/avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import Avatar from '@mui/material/Avatar';
import {FC} from "react";
import {dicebear} from "@src/utils/dicebear.ts";
import {COLORS} from "@src/layouts/config-layout.ts";

interface AvatarProfileProps {
src: string;
Expand All @@ -11,12 +12,19 @@ interface AvatarProfileProps {
}

const AvatarProfile: FC<AvatarProfileProps> = ({ src, alt, sx, ...other }) => {

//Check if src is a valid URL starting with http or https; if not, use the dicebear API to generate a random avatar
if (!src.startsWith('http') && !src.startsWith('https')) { src = dicebear(src) }
const imageSrc = src.startsWith('http') || src.startsWith('https') ? src : dicebear(src);

// Default styles for the Avatar component
sx = {
backgroundColor: COLORS.GRAY_DARK,
fontWeight: 'bold',
...sx,
};


return (
<Avatar alt={alt ?? 'Avatar profile'} src={src} sx={sx} {...other} />
<Avatar alt={alt?.toUpperCase() ?? 'Avatar profile'} src={imageSrc} sx={sx} {...other} />
)
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/user-item/BadgeVerified.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const BadgeVerified: FC<BadgeVerifiedProps> = ({ address }) => {
// If the user is not verified, do not render the badge
if (!isVerified) return null;

return <Icon width={20} color={"#FFF"} icon={"ic:round-verified"} />;
return <Icon width={20} color={"#cca421"} icon={"ic:round-verified"} />;
};

export default BadgeVerified;
2 changes: 1 addition & 1 deletion src/config-global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const GLOBAL_CONSTANTS = {
process.env.VITE_ACCESS_MANAGER_ADDRESS || import.meta.env.VITE_ACCESS_MANAGER_ADDRESS || '',
SENTRY_AUTH_TOKEN:
process.env.VITE_SENTRY_AUTH_TOKEN || import.meta.env.VITE_SENTRY_AUTH_TOKEN || '',
SENTRY_DNS: process.env.VITE_SENTRY_DNS || import.meta.env.VITE_SENTRY_DNS || '',
SENTRY_DSN: process.env.VITE_SENTRY_DSN || import.meta.env.VITE_SENTRY_DSN || '',
PINATA_API_KEY: process.env.VITE_PINATA_API_KEY || import.meta.env.VITE_PINATA_API_KEY || '',
PINATA_SECRET_API_KEY:
process.env.VITE_PINATA_SECRET_API_KEY || import.meta.env.VITE_PINATA_SECRET_API_KEY || '',
Expand Down
45 changes: 23 additions & 22 deletions src/hooks/use-referrals.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,22 @@
import { useState } from 'react';
import { useSelector } from 'react-redux';
import emailjs from '@emailjs/browser';

import { GLOBAL_CONSTANTS } from '@src/config-global';
import { useSelector } from 'react-redux';
import { Invitation } from '@src/types/invitation'; // <-- Importing from separate types file
import {
fetchInvitations as fetchInvitationsAction,
checkIfMyEmailHasPendingInvite as checkIfMyEmailHasPendingInviteAction,
acceptInvitation as acceptInvitationAction,
checkIfInvitationSent as checkIfInvitationSentAction,
checkIfEmailAlreadyAccepted as checkIfEmailAlreadyAcceptedAction,
sendInvitation as sendInvitationAction,
acceptOrCreateInvitationForUser as acceptOrCreateInvitationForUserAction
acceptOrCreateInvitationForUser as acceptOrCreateInvitationForUserAction,
} from '@src/utils/supabase-actions';

export interface Invitation {
id: string;
status: 'pending' | 'accepted' | 'rejected';
sender_email: string;
destination: string;
sender_id: string;
receiver_id: string | null;
payload: any;
created_at: string;
}

/**
* The type for sending emails through EmailJS.
*/
export type EmailParams = {
to_email: string;
from_name: string;
Expand Down Expand Up @@ -94,14 +88,18 @@ const useReferrals = () => {
setLoading(true);
setError(null);

const { data, error } = await acceptInvitationAction(invitationId, sessionData?.profile?.id);
const { data, error } = await acceptInvitationAction(
invitationId,
sessionData?.profile?.id
);

if (error) {
setError(error);
setLoading(false);
return null;
}

// Update local state to reflect the accepted status
setInvitations((prev) =>
prev.map((inv) =>
inv.id === invitationId
Expand Down Expand Up @@ -168,6 +166,7 @@ const useReferrals = () => {
* @returns {Promise<void>} - Throws an error if something goes wrong.
*/
const sendInvitation = async (destination: string, payload: any): Promise<void> => {
// Insert a new invitation into Supabase
const { error } = await sendInvitationAction(destination, payload, userEmail, sessionData);

if (error) {
Expand All @@ -176,7 +175,7 @@ const useReferrals = () => {
} else {
console.log('Invitation stored successfully in Supabase.');

// Send the email using EmailJS
// Send the email via EmailJS
await sendEmail({
to_email: destination,
from_name: payload?.data?.from?.displayName ?? 'Watchit Web3xAI',
Expand All @@ -201,13 +200,17 @@ const useReferrals = () => {
}
};

/**
* Send an email with EmailJS.
*/
const sendEmail = async (data: EmailParams) => {
const { from_name, to_email } = data;

// Set the template parameters for EmailJS
const templateParams = {
to_email,
from_name,
from_email: GLOBAL_CONSTANTS.SENDER_EMAIL,
from_email: GLOBAL_CONSTANTS.SENDER_EMAIL, // <-- Enforcing the global from_email
};

try {
Expand All @@ -233,17 +236,15 @@ const useReferrals = () => {
loading,
error,

// Fetch/CRUD Methods
// CRUD/Fetch Methods
fetchInvitations,
sendInvitation,
sendEmail,

// Additional Validation/Check Methods
checkIfMyEmailHasPendingInvite,
acceptInvitation,
checkIfInvitationSent,
checkIfEmailAlreadyAccepted,
acceptOrCreateInvitationForUser
sendInvitation,
acceptOrCreateInvitationForUser,
sendEmail,
};
};

Expand Down
3 changes: 2 additions & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ const isDevelopment = GLOBAL_CONSTANTS.ENVIRONMENT === 'development';
Sentry.init({
environment: GLOBAL_CONSTANTS.ENVIRONMENT,
enabled: !isDevelopment,
dsn: GLOBAL_CONSTANTS.SENTRY_DNS,
dsn: GLOBAL_CONSTANTS.SENTRY_DSN,
integrations: [Sentry.browserTracingIntegration(), Sentry.replayIntegration()],
// Tracing
tracesSampleRate: 1.0, // Capture 100% of the transactions
tracePropagationTargets: ["localhost", /^https:\/\/app.watchit\.movie/],
// Session Replay
replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.
replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.
Expand Down
1 change: 1 addition & 0 deletions src/layouts/_common/account-popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ export default function AccountPopover() {
}
alt="avatar"
sx={{
fontSize: '1.25rem',
width: 36,
height: 36,
border: (theme: any) => `solid 2px ${theme.palette.background.default}`,
Expand Down
33 changes: 30 additions & 3 deletions src/sections/finance/components/finance-invite-friends.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { ERRORS } from '@notifications/errors.ts';

import useReferrals from "@src/hooks/use-referrals";
import LoadingButton from '@mui/lab/LoadingButton';
import {checkIfEmailAlreadyInvited} from "@src/utils/supabase-actions.ts";

interface Props extends BoxProps {
img?: string;
Expand All @@ -42,17 +43,25 @@ export default function FinanceInviteFriends({
} = useReferrals();
const theme = useTheme();
const sessionData = useSelector((state: any) => state.auth.session);
const userLoggedEmail = useSelector((state: any) => state.auth.email);
const [email, setEmail] = useState('');
const [loading, setLoading] = useState(false);

const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setEmail(event.target.value);
};

const handleInviteClick = async () => {
// Basic email format check
/*
* Return true if the email is valid, false otherwise.
* */
const handleValidEmail = () => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
return emailRegex.test(email);
}

const handleInviteClick = async () => {

if (!handleValidEmail()) {
notifyError(ERRORS.INVITATION_EMAIL_ERROR);
return;
}
Expand All @@ -61,6 +70,23 @@ export default function FinanceInviteFriends({

// Check if there's an existing invitation from the current user to this email
const alreadySent = await checkIfInvitationSent(email);

// Check if the user has already been invited but someone else
const { invited } = await checkIfEmailAlreadyInvited(email);

if (invited) {
notifyError(ERRORS.INVITATION_USER_ALREADY_INVITED);
setLoading(false);
return;
}

// Check if the email entered is the same as the logged user's email
if (email === userLoggedEmail) {
notifyError(ERRORS.INVITATION_USER_CANT_INVITE_SELF);
setLoading(false);
return;
}

if (alreadySent) {
// You can adapt the notification message to match your requirements
notifyError(ERRORS.ALREADY_SENT_INVITATION);
Expand Down Expand Up @@ -165,6 +191,7 @@ export default function FinanceInviteFriends({
onChange={handleInputChange}
endAdornment={
<LoadingButton
disabled={!email || loading || !handleValidEmail()}
color="warning"
variant="contained"
size="small"
Expand Down
3 changes: 2 additions & 1 deletion src/sections/user/profile-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const shareLinks = [
{
icon: 'mingcute:social-x-line',
label: 'X',
url: `https://x.com/share/?url=${encodeURIComponent(urlToShare)}&text=Visit%20my%20profile%20in%20Watchit&hashtags=Watchit`,
url: `https://x.com/share/?url=${encodeURIComponent(urlToShare)}&text=Visit%20my%20profile%20on%20Watchit&hashtags=Watchit,Crypto,Blockchain`,
},
{
icon: 'mdi:facebook',
Expand Down Expand Up @@ -332,6 +332,7 @@ const ProfileHeader = ({
alt={profile?.handle?.localName ?? ''}
variant="rounded"
sx={{
fontSize: '3em',
width: { xs: 96, md: 128 },
height: { xs: 96, md: 128 },
border: `solid 2px ${theme.palette.common.white}`,
Expand Down
10 changes: 10 additions & 0 deletions src/types/invitation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export interface Invitation {
id: string;
status: 'pending' | 'accepted' | 'rejected';
sender_email: string;
destination: string;
sender_id: string;
receiver_id: string | null;
payload: any;
created_at: string;
}
4 changes: 4 additions & 0 deletions src/utils/notifications/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ export enum ERRORS {
ALREADY_SENT_INVITATION = 'ALREADY_SENT_INVITATION',
ALREADY_ENROLLED = 'ALREADY_ENROLLED',
INVITATION_SEND_ERROR = 'INVITATION_SEND_ERROR',
INVITATION_USER_ALREADY_INVITED = 'INVITATION_USER_ALREADY_INVITED',
INVITATION_USER_CANT_INVITE_SELF = 'INVITATION_USER_CANT_INVITE_SELF',
}

/**
Expand Down Expand Up @@ -113,4 +115,6 @@ export const ERROR_MESSAGES: Record<ERRORS, string> = {
[ERRORS.ALREADY_SENT_INVITATION]: 'You have already sent an invitation to this email address!',
[ERRORS.ALREADY_ENROLLED]: 'This user is already enrolled!',
[ERRORS.INVITATION_SEND_ERROR]: 'An error occurred while sending the invitation.',
[ERRORS.INVITATION_USER_ALREADY_INVITED]: 'This user has already been invited!',
[ERRORS.INVITATION_USER_CANT_INVITE_SELF]: 'You cannot invite yourself!',
};
Loading

0 comments on commit 0775c58

Please sign in to comment.