diff --git a/components/Account.js b/components/Account.js
new file mode 100644
index 0000000..e01d7e1
--- /dev/null
+++ b/components/Account.js
@@ -0,0 +1,110 @@
+import { useState, useEffect } from 'react'
+import { supabase } from '../utils/supabaseClient'
+
+export default function Account({ session }) {
+ const [loading, setLoading] = useState(true)
+ const [username, setUsername] = useState(null)
+ const [website, setWebsite] = useState(null)
+ const [avatar_url, setAvatarUrl] = useState(null)
+
+ useEffect(() => {
+ getProfile()
+ }, [session])
+
+ async function getProfile() {
+ try {
+ setLoading(true)
+ const user = supabase.auth.user()
+
+ let { data, error, status } = await supabase
+ .from('profiles')
+ .select(`username, website, avatar_url`)
+ .eq('id', user.id)
+ .single()
+
+ if (error && status !== 406) {
+ throw error
+ }
+
+ if (data) {
+ setUsername(data.username)
+ setWebsite(data.website)
+ setAvatarUrl(data.avatar_url)
+ }
+ } catch (error) {
+ alert(error.message)
+ } finally {
+ setLoading(false)
+ }
+ }
+
+ async function updateProfile({ username, website, avatar_url }) {
+ try {
+ setLoading(true)
+ const user = supabase.auth.user()
+
+ const updates = {
+ id: user.id,
+ username,
+ website,
+ avatar_url,
+ updated_at: new Date(),
+ }
+
+ let { error } = await supabase.from('profiles').upsert(updates, {
+ returning: 'minimal', // Don't return the value after inserting
+ })
+
+ if (error) {
+ throw error
+ }
+ } catch (error) {
+ alert(error.message)
+ } finally {
+ setLoading(false)
+ }
+ }
+
+ return (
+
+
+
+
+
+
+
+ setUsername(e.target.value)}
+ />
+
+
+
+ setWebsite(e.target.value)}
+ />
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/components/Auth.js b/components/Auth.js
new file mode 100644
index 0000000..57cc90f
--- /dev/null
+++ b/components/Auth.js
@@ -0,0 +1,30 @@
+import { Auth, Typography, Button } from "@supabase/ui";
+import { supabase } from "utils/supabaseClient";
+
+const { Text } = Typography;
+
+// Create a single supabase client for interacting with your database
+
+const Container = (props) => {
+ const { user } = Auth.useUser();
+ if (user)
+ return (
+ <>
+ Hello {user.email}! 👋 You are already logged in
+
+ >
+ );
+ return props.children;
+};
+
+export default function AuthComponent() {
+ return (
+
+
+
+
+
+ );
+}
diff --git a/components/Footer.js b/components/Footer.js
new file mode 100644
index 0000000..8d6a35a
--- /dev/null
+++ b/components/Footer.js
@@ -0,0 +1,9 @@
+const Nav = () => {
+ return (
+
+ );
+};
+
+export default Nav;
diff --git a/components/Layout.js b/components/Layout.js
new file mode 100644
index 0000000..8070c90
--- /dev/null
+++ b/components/Layout.js
@@ -0,0 +1,16 @@
+import Nav from "./Nav";
+import Footer from "./Footer";
+
+const Layout = (props) => {
+ return (
+
+
+
+ {props.children}
+
+
+
+ );
+};
+
+export default Layout;
diff --git a/components/Nav.js b/components/Nav.js
new file mode 100644
index 0000000..c7c4521
--- /dev/null
+++ b/components/Nav.js
@@ -0,0 +1,40 @@
+import { Menu } from "react-feather";
+import Link from "next/link";
+const Nav = () => {
+ const NavMenu = (
+ <>
+
+ Home
+
+
+ Dashboard
+
+
+ About
+
+
+ Contact
+
+ >
+ );
+
+ return (
+
+ );
+};
+
+export default Nav;
diff --git a/env.local.example b/env.local.example
new file mode 100644
index 0000000..af068a4
--- /dev/null
+++ b/env.local.example
@@ -0,0 +1,2 @@
+NEXT_PUBLIC_SUPABASE_URL=YOUR_SUPABASE_URL
+NEXT_PUBLIC_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY
\ No newline at end of file
diff --git a/jsconfig.json b/jsconfig.json
new file mode 100644
index 0000000..bcfa855
--- /dev/null
+++ b/jsconfig.json
@@ -0,0 +1,5 @@
+{
+ "compilerOptions": {
+ "baseUrl": "."
+ }
+}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index e151c2a..3cf46a6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,10 +9,13 @@
"version": "0.1.0",
"dependencies": {
"@supabase/supabase-js": "^1.15.0",
+ "@supabase/ui": "^0.27.3",
"daisyui": "^1.3.4",
"next": "latest",
+ "next-seo": "^4.24.0",
"react": "^17.0.1",
- "react-dom": "^17.0.1"
+ "react-dom": "^17.0.1",
+ "react-feather": "^2.0.9"
},
"devDependencies": {
"autoprefixer": "^10.0.4",
@@ -306,6 +309,19 @@
"@supabase/storage-js": "^1.2.1"
}
},
+ "node_modules/@supabase/ui": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@supabase/ui/-/ui-0.27.3.tgz",
+ "integrity": "sha512-SO7TO/TIK6qziHUTmd2YpTmUtpBfYrN4Gx9tL7pYDHhfmmVApmYXmxEVexHAvHkSsxaK8yPER9KbMpwXx3ZwPQ==",
+ "dependencies": {
+ "lodash": "^4.17.20",
+ "prop-types": "^15.7.2"
+ },
+ "peerDependencies": {
+ "react": "^16.13.1 || ^17.0.1",
+ "react-dom": "^16.13.1 || ^17.0.1"
+ }
+ },
"node_modules/@types/node": {
"version": "15.12.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz",
@@ -2197,6 +2213,16 @@
}
}
},
+ "node_modules/next-seo": {
+ "version": "4.24.0",
+ "resolved": "https://registry.npmjs.org/next-seo/-/next-seo-4.24.0.tgz",
+ "integrity": "sha512-9VQXfXAelhE+hAWzJ4azigQaW3FPX0kU0eYKFQXKsQjgY7AWtukjRGXls0oSIk8khhDJwmCt46EwsO9n5DDW6Q==",
+ "peerDependencies": {
+ "next": "^8.1.1-canary.54 || ^9.0.0 || ^10.0.0",
+ "react": "^16.0.0 || ^17.0.0",
+ "react-dom": "^16.0.0 || ^17.0.0"
+ }
+ },
"node_modules/next-tick": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
@@ -2984,6 +3010,17 @@
"react": "17.0.2"
}
},
+ "node_modules/react-feather": {
+ "version": "2.0.9",
+ "resolved": "https://registry.npmjs.org/react-feather/-/react-feather-2.0.9.tgz",
+ "integrity": "sha512-yMfCGRkZdXwIs23Zw/zIWCJO3m3tlaUvtHiXlW+3FH7cIT6fiK1iJ7RJWugXq7Fso8ZaQyUm92/GOOHXvkiVUw==",
+ "dependencies": {
+ "prop-types": "^15.7.2"
+ },
+ "peerDependencies": {
+ "react": "^16.8.6 || ^17"
+ }
+ },
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@@ -3995,6 +4032,15 @@
"@supabase/storage-js": "^1.2.1"
}
},
+ "@supabase/ui": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@supabase/ui/-/ui-0.27.3.tgz",
+ "integrity": "sha512-SO7TO/TIK6qziHUTmd2YpTmUtpBfYrN4Gx9tL7pYDHhfmmVApmYXmxEVexHAvHkSsxaK8yPER9KbMpwXx3ZwPQ==",
+ "requires": {
+ "lodash": "^4.17.20",
+ "prop-types": "^15.7.2"
+ }
+ },
"@types/node": {
"version": "15.12.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz",
@@ -5484,6 +5530,12 @@
}
}
},
+ "next-seo": {
+ "version": "4.24.0",
+ "resolved": "https://registry.npmjs.org/next-seo/-/next-seo-4.24.0.tgz",
+ "integrity": "sha512-9VQXfXAelhE+hAWzJ4azigQaW3FPX0kU0eYKFQXKsQjgY7AWtukjRGXls0oSIk8khhDJwmCt46EwsO9n5DDW6Q==",
+ "requires": {}
+ },
"next-tick": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
@@ -6090,6 +6142,14 @@
"scheduler": "^0.20.2"
}
},
+ "react-feather": {
+ "version": "2.0.9",
+ "resolved": "https://registry.npmjs.org/react-feather/-/react-feather-2.0.9.tgz",
+ "integrity": "sha512-yMfCGRkZdXwIs23Zw/zIWCJO3m3tlaUvtHiXlW+3FH7cIT6fiK1iJ7RJWugXq7Fso8ZaQyUm92/GOOHXvkiVUw==",
+ "requires": {
+ "prop-types": "^15.7.2"
+ }
+ },
"react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
diff --git a/package.json b/package.json
index b3351f5..c749adb 100644
--- a/package.json
+++ b/package.json
@@ -9,10 +9,13 @@
},
"dependencies": {
"@supabase/supabase-js": "^1.15.0",
+ "@supabase/ui": "^0.27.3",
"daisyui": "^1.3.4",
"next": "latest",
+ "next-seo": "^4.24.0",
"react": "^17.0.1",
- "react-dom": "^17.0.1"
+ "react-dom": "^17.0.1",
+ "react-feather": "^2.0.9"
},
"devDependencies": {
"autoprefixer": "^10.0.4",
diff --git a/pages/_app.js b/pages/_app.js
index 1040120..77508f3 100644
--- a/pages/_app.js
+++ b/pages/_app.js
@@ -1,7 +1,28 @@
-import 'tailwindcss/tailwind.css'
+import "tailwindcss/tailwind.css";
+import { Auth } from "@supabase/ui";
+import { DefaultSeo } from "next-seo";
+import { supabase } from "utils/supabaseClient";
function MyApp({ Component, pageProps }) {
- return
+ return (
+ <>
+
+
+
+
+ >
+ );
}
-export default MyApp
+export default MyApp;
diff --git a/pages/dashboard.js b/pages/dashboard.js
new file mode 100644
index 0000000..f3c674e
--- /dev/null
+++ b/pages/dashboard.js
@@ -0,0 +1,41 @@
+import Head from "next/head";
+import { useState, useEffect } from "react";
+import { supabase } from "../utils/supabaseClient";
+import Auth from "../components/Auth";
+import Account from "../components/Account";
+import Layout from "components/Layout";
+
+export default function Home() {
+ const [session, setSession] = useState(null);
+
+ useEffect(() => {
+ setSession(supabase.auth.session());
+
+ supabase.auth.onAuthStateChange((_event, session) => {
+ setSession(session);
+ });
+ }, []);
+ return (
+
+
+
Dashboard
+
+
+
+
+
+
Dashboard
+
+ {!session ? (
+
+ ) : (
+
+ )}
+
+
+
+
+ );
+}
diff --git a/pages/index.js b/pages/index.js
index 6b67e91..20ff742 100644
--- a/pages/index.js
+++ b/pages/index.js
@@ -1,82 +1,31 @@
-import Head from 'next/head'
+import Head from "next/head";
+import { useState, useEffect } from "react";
+import { supabase } from "../utils/supabaseClient";
+import Auth from "../components/Auth";
+import Account from "../components/Account";
+import Layout from "components/Layout";
export default function Home() {
+ const [session, setSession] = useState(null);
+
+ useEffect(() => {
+ setSession(supabase.auth.session());
+
+ supabase.auth.onAuthStateChange((_event, session) => {
+ setSession(session);
+ });
+ }, []);
return (
-
+
Create Next App
-
+
-
-
-
-
-
+
- )
+ );
}
diff --git a/utils/supabaseClient.js b/utils/supabaseClient.js
new file mode 100644
index 0000000..e3fcf7f
--- /dev/null
+++ b/utils/supabaseClient.js
@@ -0,0 +1,6 @@
+import { createClient } from '@supabase/supabase-js'
+
+const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL
+const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
+
+export const supabase = createClient(supabaseUrl, supabaseAnonKey)
\ No newline at end of file