diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..1ce4521 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,52 @@ +{ + "env": { + "browser": true, + "es2021": true, + "node": true, + "cypress/globals": true + }, + "extends": [ + "plugin:react/recommended", + "airbnb", + "prettier" + ], + "parserOptions": { + "ecmaFeatures": { + "jsx": true + }, + "ecmaVersion": 12, + "sourceType": "module" + }, + "plugins": [ + "react", + "cypress", + "simple-import-sort", + "prettier" + ], + "rules": { + "no-console": "off", + "react/no-unescaped-entities": "off", + "prettier/prettier": "error", + "react/react-in-jsx-scope": "off", + "react/jsx-filename-extension": [ + 2, + { + "extensions": [ + ".js", + ".jsx", + ".ts", + ".tsx" + ] + } + ] + }, + "settings": { + "import/resolver": { + "node": { + "paths": [ + "." + ] + } + } + } +} \ No newline at end of file diff --git a/.estlintignore b/.estlintignore new file mode 100644 index 0000000..56eafb5 --- /dev/null +++ b/.estlintignore @@ -0,0 +1,3 @@ +.next +dist +node_modules/ \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..3181cc9 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,5 @@ +{ + "singleQuote": true, + "tabWidth": 2, + "semi": true +} \ No newline at end of file diff --git a/components/AuthText.js b/components/AuthText.js index 1e9ffd6..7fbe50f 100644 --- a/components/AuthText.js +++ b/components/AuthText.js @@ -1,26 +1,23 @@ -import Image from "next/image"; -import authImage from "public/auth.png"; +import Image from 'next/image'; +import authImage from 'public/auth.png'; -const AuthText = () => { - return ( -
-
- -
-

- Join SupaNexTail for free! -

-

- Create your website in a few minutes with our boilerplate. You can use - the login system, this will allow you to discover the sample dashboard - page. -

+const AuthText = () => ( +
+
+
- ); -}; +

+ Join SupaNexTail for free! +

+

+ Create your website in a few minutes with our boilerplate. You can use the + login system, this will allow you to discover the sample dashboard page. +

+
+); export default AuthText; diff --git a/components/Avatar.js b/components/Avatar.js index 95f55ee..75701a5 100644 --- a/components/Avatar.js +++ b/components/Avatar.js @@ -4,9 +4,9 @@ the upload. You can tweak the max size, line 47 */ -import { useEffect, useState } from "react"; +import { useEffect, useState } from 'react'; -import { supabase } from "utils/supabaseClient"; +import { supabase } from 'utils/supabaseClient'; const Avatar = ({ url, size, onUpload }) => { const [avatarUrl, setAvatarUrl] = useState(null); @@ -19,7 +19,7 @@ const Avatar = ({ url, size, onUpload }) => { async function downloadImage(path) { try { const { data, error } = await supabase.storage - .from("avatars") + .from('avatars') .download(path); if (error) { throw error; @@ -27,7 +27,7 @@ const Avatar = ({ url, size, onUpload }) => { const url = URL.createObjectURL(data); setAvatarUrl(url); } catch (error) { - console.log("Error downloading image: ", error.message); + console.log('Error downloading image: ', error.message); } } @@ -36,23 +36,23 @@ const Avatar = ({ url, size, onUpload }) => { setUploading(true); if (!event.target.files || event.target.files.length === 0) { - throw new Error("You must select an image to upload."); + throw new Error('You must select an image to upload.'); } const file = event.target.files[0]; - const fileExt = file.name.split(".").pop(); + const fileExt = file.name.split('.').pop(); const fileName = `${Math.random()}.${fileExt}`; const filePath = `${fileName}`; if (event.target.files[0].size > 150000) { - alert("File is too big!"); - event.target.value = ""; - setUploading(false) + alert('File is too big!'); + event.target.value = ''; + setUploading(false); return; } - let { error: uploadError } = await supabase.storage - .from("avatars") + const { error: uploadError } = await supabase.storage + .from('avatars') .upload(filePath, file); if (uploadError) { @@ -68,30 +68,31 @@ const Avatar = ({ url, size, onUpload }) => { } return ( -
+
{avatarUrl ? ( Avatar ) : ( -
+
)}
diff --git a/components/CardsLanding.js b/components/CardsLanding.js index 693b10e..b1f259e 100644 --- a/components/CardsLanding.js +++ b/components/CardsLanding.js @@ -1,62 +1,60 @@ -import CardLanding from "components/UI/CardLanding"; -import cardAuth from "public/landing/auth.svg"; -import cardFee from "public/landing/lifetime.svg"; -import cardPage from "public/landing/page.svg"; -import cardResponsive from "public/landing/responsive.svg"; -import cardServer from "public/landing/backend.svg"; -import cardStripe from "public/landing/stripe.svg"; -import cardTheme from "public/landing/theme.svg"; +import CardLanding from 'components/UI/CardLanding'; +import cardAuth from 'public/landing/auth.svg'; +import cardFee from 'public/landing/lifetime.svg'; +import cardPage from 'public/landing/page.svg'; +import cardResponsive from 'public/landing/responsive.svg'; +import cardServer from 'public/landing/backend.svg'; +import cardStripe from 'public/landing/stripe.svg'; +import cardTheme from 'public/landing/theme.svg'; -const CardsLanding = () => { - return ( -
-

- We've got you covered -

-

- Don’t waste your time and reinvent the wheel, we have provided you with - a maximum of features so that you only have one goal, to make your SaaS - a reality. -

-
- - - - - - - -
+const CardsLanding = () => ( +
+

+ We've got you covered +

+

+ Don’t waste your time and reinvent the wheel, we have provided you with a + maximum of features so that you only have one goal, to make your SaaS a + reality. +

+
+ + + + + + +
- ); -}; +
+); export default CardsLanding; diff --git a/components/Contact.js b/components/Contact.js index 6eac051..9c878ed 100644 --- a/components/Contact.js +++ b/components/Contact.js @@ -6,32 +6,32 @@ If you want to change the email provider, don't hesitate to create a new api rou the axios.post here, line 18. */ -import axios from "axios"; -import { toast } from "react-toastify"; +import axios from 'axios'; +import { toast } from 'react-toastify'; const Contact = () => { const sendEmail = () => { - const name = document.getElementById("name").value; - const email = document.getElementById("email").value; - const message = document.getElementById("message").value; + const name = document.getElementById('name').value; + const email = document.getElementById('email').value; + const message = document.getElementById('message').value; if (name && email && message) { axios - .post("/api/sendgrid", { email, name, message }) + .post('/api/sendgrid', { email, name, message }) .then((result) => { if (result.data.success === true) { toast.success(result.data.message); - document.getElementById("name").value = ""; - document.getElementById("email").value = ""; - document.getElementById("message").value = ""; + document.getElementById('name').value = ''; + document.getElementById('email').value = ''; + document.getElementById('message').value = ''; } }) .catch((err) => { console.log(err); }); } else { - toast.info("Please enter at least one URL", { - position: "top-center", + toast.info('Please enter at least one URL', { + position: 'top-center', autoClose: 2000, hideProgressBar: true, closeOnClick: true, @@ -42,51 +42,56 @@ const Contact = () => { } }; return ( -
+
-
-

+
+

Contact

-

+

Do you have a question about SupaNexTail? A cool feature you'd like us to integrate? A bug to report? Don't hesitate!

-
-
- + +
+

Your Name

+ id="name" + name="name" + placeholder="Enter your name" + className="input input-primary input-bordered" + />
-
- +
+

Your email

+ id="email" + name="email" + placeholder="Enter your email adress" + className="input input-primary input-bordered" + />
-
- +
+

Message

+ id="message" + name="message" + placeholder="Enter your message here..." + rows="5" + className="input input-primary input-bordered resize-none w-full h-32 pt-2" + />
diff --git a/components/Dashboard.js b/components/Dashboard.js index 786138f..515699b 100644 --- a/components/Dashboard.js +++ b/components/Dashboard.js @@ -5,16 +5,16 @@ function with your new elements. It also show you the current subscription plan */ -import { useEffect, useState } from "react"; +import { useEffect, useState } from 'react'; -import Avatar from "./Avatar"; -import Image from "next/image"; -import PaymentModal from "./PaymentModal"; -import Plan from "public/plan.svg"; -import { PriceIds } from "utils/priceList"; -import { supabase } from "../utils/supabaseClient"; -import { toast } from "react-toastify"; -import { useRouter } from "next/router"; +import Image from 'next/image'; +import Plan from 'public/plan.svg'; +import { PriceIds } from 'utils/priceList'; +import { toast } from 'react-toastify'; +import { useRouter } from 'next/router'; +import { supabase } from '../utils/supabaseClient'; +import PaymentModal from './PaymentModal'; +import Avatar from './Avatar'; export default function Dashboard(props) { const router = useRouter(); @@ -25,7 +25,7 @@ export default function Dashboard(props) { const [payment, setPayment] = useState(false); useEffect(() => { - if (router.query.session_id && router.query.session_id !== "canceled") { + if (router.query.session_id && router.query.session_id !== 'canceled') { setPayment(true); } }, []); @@ -43,8 +43,8 @@ export default function Dashboard(props) { updated_at: new Date(), }; - let { error } = await supabase.from("profiles").upsert(updates, { - returning: "minimal", // Don't return the value after inserting + const { error } = await supabase.from('profiles').upsert(updates, { + returning: 'minimal', // Don't return the value after inserting }); if (error) { @@ -54,14 +54,14 @@ export default function Dashboard(props) { alert(error.message); } finally { setLoading(false); - toast.success("Your profile has been updated"); + toast.success('Your profile has been updated'); } } return ( -
-
-

+
+
+

Dashboard

-
-