mirror of
https://github.com/fergalmoran/supanextail.git
synced 2025-12-22 09:17:54 +00:00
Clean V2 - Add sonarjs and unicorn js
This commit is contained in:
@@ -9,25 +9,25 @@ import React, { useEffect, useState } from 'react';
|
||||
import Image from 'next/image';
|
||||
import { supabase } from 'utils/supabaseClient';
|
||||
|
||||
type AvatarProps = {
|
||||
type AvatarProperties = {
|
||||
url: string;
|
||||
size: number;
|
||||
onUpload: (filePath: string) => void;
|
||||
};
|
||||
|
||||
const Avatar = ({ url, size, onUpload }: AvatarProps): JSX.Element => {
|
||||
const customImgLoader = ({ src }: { src: string }): string => {
|
||||
return `${src}`;
|
||||
};
|
||||
|
||||
const Avatar = ({ url, size, onUpload }: AvatarProperties): JSX.Element => {
|
||||
const [avatarUrl, setAvatarUrl] = useState('');
|
||||
const [uploading, setUploading] = useState(false);
|
||||
|
||||
const customImgLoader = ({ src }: { src: string }) => {
|
||||
return `${src}`;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (url) downloadImage(url);
|
||||
if (url) void downloadImage(url);
|
||||
}, [url]);
|
||||
|
||||
async function downloadImage(path: string) {
|
||||
async function downloadImage(path: string): Promise<void> {
|
||||
try {
|
||||
const { data, error } = await supabase.storage
|
||||
.from('avatars')
|
||||
@@ -41,12 +41,14 @@ const Avatar = ({ url, size, onUpload }: AvatarProps): JSX.Element => {
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof Error) {
|
||||
console.log('Error downloading image: ', error.message);
|
||||
console.log('Error downloading image:', error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function uploadAvatar(event: React.ChangeEvent<HTMLInputElement>) {
|
||||
async function uploadAvatar(
|
||||
event: React.ChangeEvent<HTMLInputElement>
|
||||
): Promise<void> {
|
||||
try {
|
||||
setUploading(true);
|
||||
|
||||
@@ -55,11 +57,11 @@ const Avatar = ({ url, size, onUpload }: AvatarProps): JSX.Element => {
|
||||
}
|
||||
|
||||
const file = event.target.files[0];
|
||||
const fileExt = file.name.split('.').pop();
|
||||
const fileName = `${Math.random()}.${fileExt}`;
|
||||
const fileExtension = file.name.split('.').pop();
|
||||
const fileName = fileExtension ? `${Math.random()}.${fileExtension}` : '';
|
||||
const filePath = `${fileName}`;
|
||||
|
||||
if (event.target.files[0].size > 150000) {
|
||||
if (event.target.files[0].size > 150_000) {
|
||||
alert('File is too big!');
|
||||
event.target.value = '';
|
||||
setUploading(false);
|
||||
|
||||
@@ -9,39 +9,47 @@ the axios.post here, line 18.
|
||||
import axios from 'axios';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
const Contact = (): JSX.Element => {
|
||||
const sendEmail = () => {
|
||||
const name = (document.getElementById('name') as HTMLInputElement).value;
|
||||
const email = (document.getElementById('email') as HTMLInputElement).value;
|
||||
const message = (document.getElementById('message') as HTMLInputElement)
|
||||
.value;
|
||||
const sendEmail = (): void => {
|
||||
const name = (document.querySelector('#name') as HTMLInputElement).value;
|
||||
const email = (document.querySelector('#email') as HTMLInputElement).value;
|
||||
const message = (document.querySelector('#message') as HTMLInputElement)
|
||||
.value;
|
||||
|
||||
if (name && email && message) {
|
||||
axios
|
||||
.post('/api/sendgrid', { email, name, message })
|
||||
.then((result) => {
|
||||
if (name && email && message) {
|
||||
axios
|
||||
.post('/api/sendgrid', { email, name, message })
|
||||
.then(
|
||||
(result: {
|
||||
data: {
|
||||
success: boolean;
|
||||
message: string;
|
||||
};
|
||||
}) => {
|
||||
if (result.data.success === true) {
|
||||
toast.success(result.data.message);
|
||||
(document.getElementById('name') as HTMLInputElement).value = '';
|
||||
(document.getElementById('email') as HTMLInputElement).value = '';
|
||||
(document.getElementById('message') as HTMLInputElement).value = '';
|
||||
(document.querySelector('#name') as HTMLInputElement).value = '';
|
||||
(document.querySelector('#email') as HTMLInputElement).value = '';
|
||||
(document.querySelector('#message') as HTMLInputElement).value = '';
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
} else {
|
||||
toast.info('Please fill all the fields ', {
|
||||
position: 'top-center',
|
||||
autoClose: 2000,
|
||||
hideProgressBar: true,
|
||||
closeOnClick: true,
|
||||
pauseOnHover: true,
|
||||
draggable: true,
|
||||
progress: undefined,
|
||||
}
|
||||
)
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
};
|
||||
} else {
|
||||
toast.info('Please fill all the fields ', {
|
||||
position: 'top-center',
|
||||
autoClose: 2000,
|
||||
hideProgressBar: true,
|
||||
closeOnClick: true,
|
||||
pauseOnHover: true,
|
||||
draggable: true,
|
||||
progress: undefined,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const Contact = (): JSX.Element => {
|
||||
return (
|
||||
<div className="max-w-xl px-5 py-10 m-auto">
|
||||
<div>
|
||||
@@ -87,8 +95,8 @@ const Contact = (): JSX.Element => {
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary btn-sm"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
sendEmail();
|
||||
}}>
|
||||
Submit{' '}
|
||||
|
||||
@@ -16,7 +16,7 @@ import { supabase } from '../utils/supabaseClient';
|
||||
import { toast } from 'react-toastify';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
type DashboardProps = {
|
||||
type DashboardProperties = {
|
||||
profile: { username: string; website: string; avatar_url: string };
|
||||
session: Session;
|
||||
planName: string;
|
||||
@@ -26,7 +26,7 @@ const Dashboard = ({
|
||||
profile,
|
||||
session,
|
||||
planName,
|
||||
}: DashboardProps): JSX.Element => {
|
||||
}: DashboardProperties): JSX.Element => {
|
||||
const router = useRouter();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [username, setUsername] = useState(profile?.username || '');
|
||||
@@ -48,7 +48,7 @@ const Dashboard = ({
|
||||
username: string;
|
||||
website: string;
|
||||
avatar_url: string;
|
||||
}) {
|
||||
}): Promise<void> {
|
||||
try {
|
||||
setLoading(true);
|
||||
const user = supabase.auth.user();
|
||||
@@ -89,7 +89,7 @@ const Dashboard = ({
|
||||
size={150}
|
||||
onUpload={(url) => {
|
||||
setAvatarUrl(url);
|
||||
updateProfile({ username, website, avatar_url: url });
|
||||
void updateProfile({ username, website, avatar_url: url });
|
||||
}}
|
||||
/>
|
||||
<div className="flex flex-col mb-5">
|
||||
@@ -125,7 +125,7 @@ const Dashboard = ({
|
||||
id="website"
|
||||
type="website"
|
||||
value={website || ''}
|
||||
onChange={(e) => setWebsite(e.target.value)}
|
||||
onChange={(event) => setWebsite(event.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -18,11 +18,11 @@ import Nav from './Nav';
|
||||
import { ToastContainer } from 'react-toastify';
|
||||
import { useAuth } from 'utils/AuthContext';
|
||||
|
||||
type LayoutProps = {
|
||||
type LayoutProperties = {
|
||||
children: JSX.Element;
|
||||
};
|
||||
|
||||
const Layout = ({ children }: LayoutProps): JSX.Element => {
|
||||
const Layout = ({ children }: LayoutProperties): JSX.Element => {
|
||||
const { user, signOut } = useAuth();
|
||||
|
||||
return (
|
||||
|
||||
@@ -17,7 +17,7 @@ const MailingList = (): JSX.Element => {
|
||||
const validateEmail = () => {
|
||||
// Regex patern for email validation
|
||||
const regex =
|
||||
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
/^(([^\s"(),.:;<>@[\\\]]+(\.[^\s"(),.:;<>@[\\\]]+)*)|(".+"))@((\[(?:\d{1,3}\.){3}\d{1,3}])|(([\dA-Za-z\-]+\.)+[A-Za-z]{2,}))$/;
|
||||
|
||||
if (regex.test(mail)) {
|
||||
// this is a valid email address
|
||||
@@ -42,8 +42,8 @@ const MailingList = (): JSX.Element => {
|
||||
setLoading(false);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -8,12 +8,12 @@ import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import Logo from 'public/logo.svg';
|
||||
|
||||
type NavProps = {
|
||||
type NavProperties = {
|
||||
user: Record<string, unknown>;
|
||||
signOut: () => void;
|
||||
};
|
||||
|
||||
const Nav = ({ user, signOut }: NavProps): JSX.Element => {
|
||||
const Nav = ({ user, signOut }: NavProperties): JSX.Element => {
|
||||
// Modify you menu directly here
|
||||
const NavMenu = (
|
||||
<>
|
||||
|
||||
@@ -2,12 +2,15 @@ import { Dialog, Transition } from '@headlessui/react';
|
||||
|
||||
import { Fragment } from 'react';
|
||||
|
||||
type PaymentModalProps = {
|
||||
type PaymentModalProperties = {
|
||||
open: boolean;
|
||||
setPayment: (arg0: boolean) => void;
|
||||
setPayment: (argument0: boolean) => void;
|
||||
};
|
||||
|
||||
const PaymentModal = ({ open, setPayment }: PaymentModalProps): JSX.Element => {
|
||||
const PaymentModal = ({
|
||||
open,
|
||||
setPayment,
|
||||
}: PaymentModalProperties): JSX.Element => {
|
||||
function closeModal() {
|
||||
setPayment(false);
|
||||
}
|
||||
|
||||
@@ -12,12 +12,12 @@ import { SupabaseClient } from '@supabase/supabase-js';
|
||||
import { supabase } from 'utils/supabaseClient';
|
||||
import { useAuth } from 'utils/AuthContext';
|
||||
|
||||
type ContainerProps = {
|
||||
type ContainerProperties = {
|
||||
children: JSX.Element;
|
||||
supabaseClient: SupabaseClient;
|
||||
};
|
||||
|
||||
const Container = ({ children }: ContainerProps): JSX.Element => {
|
||||
const Container = ({ children }: ContainerProperties): JSX.Element => {
|
||||
const { user, signOut } = useAuth();
|
||||
if (user)
|
||||
return (
|
||||
|
||||
@@ -4,13 +4,17 @@ This card is used on the landing page
|
||||
|
||||
import Image from 'next/image';
|
||||
|
||||
type CardLandingProps = {
|
||||
type CardLandingProperties = {
|
||||
image: string;
|
||||
title: string;
|
||||
text: string;
|
||||
};
|
||||
|
||||
const CardLanding = ({ image, title, text }: CardLandingProps): JSX.Element => {
|
||||
const CardLanding = ({
|
||||
image,
|
||||
title,
|
||||
text,
|
||||
}: CardLandingProperties): JSX.Element => {
|
||||
return (
|
||||
<div className="flex h-48 p-5 mb-5 w-80 sm:ml-5 bg-base-100">
|
||||
<div>
|
||||
|
||||
@@ -4,11 +4,11 @@ This card is used on the landing page
|
||||
|
||||
import { FiStar } from 'react-icons/fi';
|
||||
|
||||
type KeyFeatureProps = {
|
||||
type KeyFeatureProperties = {
|
||||
children: JSX.Element;
|
||||
};
|
||||
|
||||
const KeyFeature = ({ children }: KeyFeatureProps): JSX.Element => (
|
||||
const KeyFeature = ({ children }: KeyFeatureProperties): JSX.Element => (
|
||||
<div className="flex p-5 mb-5 italic shadow-sm bg-base-100">
|
||||
<div className="flex w-12 h-12 p-2 my-auto text-white rounded-sm bg-accent-focus">
|
||||
<FiStar className="m-auto text-2xl" />
|
||||
|
||||
@@ -3,7 +3,7 @@ import router from 'next/router';
|
||||
import { toast } from 'react-toastify';
|
||||
import { useState } from 'react';
|
||||
|
||||
type LoginProps = {
|
||||
type LoginProperties = {
|
||||
resetPassword: (email: string) => Promise<{ error: { message: string } }>;
|
||||
signIn: ({}) => Promise<{
|
||||
data: Record<string, unknown>;
|
||||
@@ -11,24 +11,28 @@ type LoginProps = {
|
||||
}>;
|
||||
};
|
||||
|
||||
const Login = ({ resetPassword, signIn }: LoginProps): JSX.Element => {
|
||||
const Login = ({ resetPassword, signIn }: LoginProperties): JSX.Element => {
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [forgot, setForgot] = useState(false);
|
||||
|
||||
const resetPasswordLogin = () => {
|
||||
resetPassword(email).then((result: { error: { message: string } }) => {
|
||||
if (result.error) {
|
||||
toast.error(result.error.message);
|
||||
} else toast.success('Check your email to reset your password!');
|
||||
});
|
||||
const resetPasswordLogin = async (): Promise<void> => {
|
||||
await resetPassword(email).then(
|
||||
(result: { error: { message: string } }) => {
|
||||
if (result.error) {
|
||||
toast.error(result.error.message);
|
||||
} else toast.success('Check your email to reset your password!');
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const login = (e: React.SyntheticEvent<HTMLButtonElement>) => {
|
||||
e.preventDefault();
|
||||
const login = async (
|
||||
event: React.SyntheticEvent<HTMLButtonElement>
|
||||
): Promise<void> => {
|
||||
event.preventDefault();
|
||||
|
||||
// Handle the login. Go to the homepage if success or display an error.
|
||||
signIn({
|
||||
await signIn({
|
||||
email,
|
||||
password,
|
||||
}).then(
|
||||
@@ -37,7 +41,7 @@ const Login = ({ resetPassword, signIn }: LoginProps): JSX.Element => {
|
||||
error: { message: string };
|
||||
}) => {
|
||||
if (result.data) {
|
||||
router.push('/');
|
||||
void router.push('/');
|
||||
}
|
||||
if (result.error) {
|
||||
toast.error(result.error.message);
|
||||
@@ -97,7 +101,7 @@ const Login = ({ resetPassword, signIn }: LoginProps): JSX.Element => {
|
||||
<button
|
||||
className="w-full btn btn-primary"
|
||||
onClick={(event) => {
|
||||
login(event);
|
||||
void login(event);
|
||||
}}>
|
||||
Log in
|
||||
</button>
|
||||
@@ -113,7 +117,7 @@ const Login = ({ resetPassword, signIn }: LoginProps): JSX.Element => {
|
||||
className="flex items-center justify-center px-4 py-2 space-x-2 transition-colors duration-300 border rounded-md focus:outline-none border-base-200 group hover:bg-base-300"
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
signIn({ provider: 'google' });
|
||||
void signIn({ provider: 'google' });
|
||||
}}>
|
||||
<div className="text-base-content">
|
||||
<IoLogoGoogle />
|
||||
@@ -154,7 +158,7 @@ const Login = ({ resetPassword, signIn }: LoginProps): JSX.Element => {
|
||||
className="w-full btn btn-primary btn-sm"
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
resetPasswordLogin();
|
||||
void resetPasswordLogin();
|
||||
}}>
|
||||
Recover my password
|
||||
</button>
|
||||
|
||||
@@ -3,7 +3,7 @@ import router from 'next/router';
|
||||
import { toast } from 'react-toastify';
|
||||
import { useState } from 'react';
|
||||
|
||||
type SignUpPanelProps = {
|
||||
type SignUpPanelProperties = {
|
||||
signIn: ({}) => Promise<{
|
||||
data: Record<string, unknown>;
|
||||
error: { message: string };
|
||||
@@ -14,19 +14,23 @@ type SignUpPanelProps = {
|
||||
}>;
|
||||
};
|
||||
|
||||
const SignUpPanel = ({ signIn, signUp }: SignUpPanelProps): JSX.Element => {
|
||||
const SignUpPanel = ({
|
||||
signIn,
|
||||
signUp,
|
||||
}: SignUpPanelProperties): JSX.Element => {
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
|
||||
const signup = (e: React.SyntheticEvent<HTMLButtonElement>) => {
|
||||
e.preventDefault();
|
||||
const signup = async (
|
||||
event: React.SyntheticEvent<HTMLButtonElement>
|
||||
): Promise<void> => {
|
||||
event.preventDefault();
|
||||
|
||||
// Handle the login. Go to the homepage if success or display an error.
|
||||
signUp({
|
||||
await signUp({
|
||||
email,
|
||||
password,
|
||||
}).then((result) => {
|
||||
console.log(result);
|
||||
if (result.error) {
|
||||
toast.error(result.error.message);
|
||||
} else if (result.data?.confirmation_sent_at) {
|
||||
@@ -35,7 +39,7 @@ const SignUpPanel = ({ signIn, signUp }: SignUpPanelProps): JSX.Element => {
|
||||
'A confirmation email has been sent to you, watch your mailbox!'
|
||||
);
|
||||
} else if (result.data) {
|
||||
router.push('/');
|
||||
void router.push('/');
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -78,7 +82,7 @@ const SignUpPanel = ({ signIn, signUp }: SignUpPanelProps): JSX.Element => {
|
||||
id="loginBtn"
|
||||
className="w-full btn btn-primary"
|
||||
onClick={(event) => {
|
||||
signup(event);
|
||||
void signup(event);
|
||||
}}>
|
||||
Sign Up
|
||||
</button>
|
||||
@@ -94,7 +98,7 @@ const SignUpPanel = ({ signIn, signUp }: SignUpPanelProps): JSX.Element => {
|
||||
className="flex items-center justify-center px-4 py-2 space-x-2 transition-colors duration-300 border rounded-md focus:outline-none border-base-200 group hover:bg-base-300"
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
signIn({ provider: 'google' });
|
||||
void signIn({ provider: 'google' });
|
||||
}}>
|
||||
<div className="text-base-content">
|
||||
<IoLogoGoogle />
|
||||
|
||||
Reference in New Issue
Block a user