Skip to content

Commit e55981f

Browse files
add login to app
1 parent bcab44b commit e55981f

File tree

11 files changed

+633
-1868
lines changed

11 files changed

+633
-1868
lines changed

package-lock.json

Lines changed: 383 additions & 1320 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"mailchimp-api-v3": "^1.15.0",
3939
"marked": "^4.0.18",
4040
"next": "12.2.2",
41+
"next-auth": "^4.24.10",
4142
"next-pwa": "^5.5.4",
4243
"next-react-svg": "^1.1.3",
4344
"next-seo": "^5.5.0",

src/components/social-share/layout-01/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ const SocialShare = () => {
2828
<div
2929
className={clsx(
3030
"tw-absolute tw-bottom-full tw-left-1/2 -tw-translate-x-1/2 -tw-translate-y-2.5 tw-w-auto tw-whitespace-nowrap tw-px-1 tw-bg-white tw-rounded tw-shadow-3sm tw-shadow-black/[.06]",
31-
"tw-drop-shadow-[0_2px_20px_rgba(0,0,0,0.06)] tw-z-10 tw-select-none tw-transition-all tw-duration-300 tw-ease-[cubic-bezier(.71,1.7,.77,1.24)] tw-invisible tw-opacity-0",
31+
"tw-drop-shadow-[0_2px_20px_rgba(0,0,0,0.06)] tw-z-10 tw-select-none tw-transition-all tw-duration-300 tw-ease-&lsqb;cubic-bezier(.71,1.7,.77,1.24)&rsqb; tw-invisible tw-opacity-0",
3232
"before:tw-absolute before:tw-content-[''] before:tw-top-full before:tw-left-1/2 before:-tw-translate-x-1/2 before:tw-border-t-8 before:tw-border-t-white before:tw-border-x-[9px] before:tw-border-x-transparent before:tw-invisible before:tw-opacity-0",
3333
"after:tw-absolute after:tw-content-[''] after:tw-left-0 after:-tw-bottom-6 after:tw-w-full after:tw-h-7",
3434
"group-hover:tw-visible group-hover:tw-opacity-100 group-hover:-tw-translate-x-1/2 group-hover:-tw-translate-y-5 group-hover:before:tw-visible group-hover:before:tw-opacity-100"

src/components/social-share/layout-01/social-link.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ const SocialLink = ({ children, href, label, onClick }: TProps) => {
1313
<a
1414
className={clsx(
1515
"tw-relative tw-inline-block tw-text-base tw-py-2.5 tw-px-3.8 tw-text-gray-400",
16-
"before:tw-absolute before:tw-content-[''] before:tw-border-[7px] before:tw-border-transparent before:tw-border-t-primary before:tw-bottom-full before:left-[calc(50%_-_7px) before:tw-transition-all before:tw-duration-300 before:tw-ease-[cubic-bezier(.71,1.7,.77,1.24)] before:tw-pointer-events-none before:tw-z-20 before:tw-mb-[-13px] before:tw-invisible before:tw-opacity-0",
17-
"after:tw-absolute after:tw-content-[attr(aria-label)] after:tw-bg-primary after:tw-text-white after:tw-py-2 after:tw-px-2.5 after:tw-leading-none after:tw-whitespace-nowrap after:tw-rounded after:tw-shadow-xs after:tw-shadow-black/30 after:tw-bottom-full after:tw-left-1/2 after:-tw-translate-x-1/2 after:tw-transition-all after:tw-duration-300 after:tw-ease-[cubic-bezier(.71,1.7,.77,1.24)] after:tw-pointer-events-none after:tw-z-10 after:tw-invisible after:tw-opacity-0",
16+
"before:tw-absolute before:tw-content-[''] before:tw-border-[7px] before:tw-border-transparent before:tw-border-t-primary before:tw-bottom-full before:left-[calc(50%_-_7px) before:tw-transition-all before:tw-duration-300 before:tw-ease-&lsqb;cubic-bezier(.71,1.7,.77,1.24)&rsqb; before:tw-pointer-events-none before:tw-z-20 before:tw-mb-[-13px] before:tw-invisible before:tw-opacity-0",
17+
"after:tw-absolute after:tw-content-[attr(aria-label)] after:tw-bg-primary after:tw-text-white after:tw-py-2 after:tw-px-2.5 after:tw-leading-none after:tw-whitespace-nowrap after:tw-rounded after:tw-shadow-xs after:tw-shadow-black/30 after:tw-bottom-full after:tw-left-1/2 after:-tw-translate-x-1/2 after:tw-transition-all after:tw-duration-300 after:tw-ease-&lsqb;cubic-bezier(.71,1.7,.77,1.24)&rsqb; after:tw-pointer-events-none after:tw-z-10 after:tw-invisible after:tw-opacity-0",
1818
"hover:before:tw-visible hover:before:tw-opacity-100 hover:before:tw-delay-100 hover:before:-tw-translate-y-2 hover:after:tw-visible hover:after:tw-opacity-100 hover:after:tw-delay-100 hover:after:-tw-translate-y-2"
1919
)}
2020
href={href}

src/components/ui/social/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ const Social = ({
4949
return null;
5050
});
5151
const flyoutClass =
52-
"tw-absolute tw-bottom-full tw-right-0 -tw-translate-y-2.5 tw-w-auto tw-whitespace-nowrap tw-px-1 tw-bg-white tw-rounded tw-shadow-3sm tw-shadow-black/[.06] tw-drop-shadow-[0_2px_20px_rgba(0,0,0,0.06)] tw-z-10 tw-select-none tw-transition-all tw-duration-300 tw-ease-[cubic-bezier(.71,1.7,.77,1.24)] tw-invisible tw-opacity-0";
52+
"tw-absolute tw-bottom-full tw-right-0 -tw-translate-y-2.5 tw-w-auto tw-whitespace-nowrap tw-px-1 tw-bg-white tw-rounded tw-shadow-3sm tw-shadow-black/[.06] tw-drop-shadow-[0_2px_20px_rgba(0,0,0,0.06)] tw-z-10 tw-select-none tw-transition-all tw-duration-300 tw-ease-&lsqb;cubic-bezier(.71,1.7,.77,1.24)&rsqb; tw-invisible tw-opacity-0";
5353
const flyoutBeforeClass =
5454
"before:tw-absolute before:tw-content-[''] before:tw-top-full before:tw-right-5 before:tw-border-t-8 before:tw-border-t-white before:tw-border-x-[9px] before:tw-border-x-transparent before:tw-invisible before:tw-opacity-0";
5555
const flyoutAfterClass =

src/components/ui/social/social-link.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ const SocialLink = ({
3939

4040
// Toopltip
4141
const tooltipBeforeClass =
42-
"before:tw-absolute before:tw-content-[''] before:tw-border-[7px] before:tw-border-transparent before:tw-border-t-primary before:tw-bottom-full before:left-[calc(50%_-_7px) before:tw-transition-all before:tw-duration-300 before:tw-ease-[cubic-bezier(.71,1.7,.77,1.24)] before:tw-pointer-events-none before:tw-z-20 before:tw-mb-[-13px] before:tw-invisible before:tw-opacity-0";
42+
"before:tw-absolute before:tw-content-[''] before:tw-border-[7px] before:tw-border-transparent before:tw-border-t-primary before:tw-bottom-full before:left-[calc(50%_-_7px) before:tw-transition-all before:tw-duration-300 before:tw-ease-&lsqb;cubic-bezier(.71,1.7,.77,1.24)&rsqb; before:tw-pointer-events-none before:tw-z-20 before:tw-mb-[-13px] before:tw-invisible before:tw-opacity-0";
4343
const tooltipAfterClass =
44-
"after:tw-absolute after:tw-content-[attr(aria-label)] after:tw-bg-primary after:tw-text-white after:tw-py-2 after:tw-px-2.5 after:tw-leading-none after:tw-whitespace-nowrap after:tw-rounded after:tw-shadow-xs after:tw-shadow-black/30 after:tw-bottom-full after:tw-left-1/2 after:-tw-translate-x-1/2 after:tw-transition-all after:tw-duration-300 after:tw-ease-[cubic-bezier(.71,1.7,.77,1.24)] after:tw-pointer-events-none after:tw-z-10 after:tw-invisible after:tw-opacity-0";
44+
"after:tw-absolute after:tw-content-[attr(aria-label)] after:tw-bg-primary after:tw-text-white after:tw-py-2 after:tw-px-2.5 after:tw-leading-none after:tw-whitespace-nowrap after:tw-rounded after:tw-shadow-xs after:tw-shadow-black/30 after:tw-bottom-full after:tw-left-1/2 after:-tw-translate-x-1/2 after:tw-transition-all after:tw-duration-300 after:tw-ease-&lsqb;cubic-bezier(.71,1.7,.77,1.24)&rsqb; after:tw-pointer-events-none after:tw-z-10 after:tw-invisible after:tw-opacity-0";
4545
const tooltipHoverClass =
4646
"hover:before:tw-visible hover:before:tw-opacity-100 hover:before:tw-delay-100 hover:before:-tw-translate-y-2 hover:after:tw-visible hover:after:tw-opacity-100 hover:after:tw-delay-100 hover:after:-tw-translate-y-2";
4747

src/pages/_app.tsx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ElementType, useEffect } from "react";
22
import { useRouter } from "next/router";
33
import type { AppProps } from "next/app";
4+
import { SessionProvider } from "next-auth/react"; // Import SessionProvider
45
import SEO from "@components/seo/deafult-seo";
56
import FallbackLayout from "@layout/fallback";
67
import "@assets/css/font-awesome-pro.min.css";
@@ -17,6 +18,7 @@ interface CustomAppProps extends Omit<AppProps, "Component"> {
1718
Component: AppProps["Component"] & { Layout: ElementType };
1819
pageProps: {
1920
[key: string]: unknown;
21+
session?: unknown; // Add session type for NextAuth
2022
};
2123
}
2224

@@ -27,7 +29,6 @@ const MyApp = ({ Component, pageProps }: CustomAppProps) => {
2729
typeof pageProps.layout === "object" ? pageProps.layout : {};
2830

2931
useEffect(() => {
30-
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
3132
document.activeElement instanceof HTMLElement &&
3233
document.activeElement.blur();
3334
}, [router]);
@@ -37,14 +38,16 @@ const MyApp = ({ Component, pageProps }: CustomAppProps) => {
3738
});
3839

3940
return (
40-
<UIProvider>
41-
<UserProvider>
42-
<Layout {...layoutProps}>
43-
<SEO />
44-
<Component {...pageProps} />
45-
</Layout>
46-
</UserProvider>
47-
</UIProvider>
41+
<SessionProvider session={pageProps.session}> {/* Wrap everything in SessionProvider */}
42+
<UIProvider>
43+
<UserProvider>
44+
<Layout {...layoutProps}>
45+
<SEO />
46+
<Component {...pageProps} />
47+
</Layout>
48+
</UserProvider>
49+
</UIProvider>
50+
</SessionProvider>
4851
);
4952
};
5053

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import NextAuth from "next-auth";
2+
import GitHubProvider from "next-auth/providers/github";
3+
4+
export const authOptions = {
5+
providers: [
6+
GitHubProvider({
7+
clientId: process.env.GITHUB_CLIENT_ID,
8+
clientSecret: process.env.GITHUB_CLIENT_SECRET,
9+
authorization: {
10+
params: {
11+
scope: "read:org",
12+
},
13+
},
14+
}),
15+
],
16+
callbacks: {
17+
async signIn({ account }) {
18+
if (account.provider === "github") {
19+
try {
20+
const res = await fetch(
21+
"https://api.github.com/user/orgs",
22+
{
23+
headers: {
24+
Authorization: `Bearer ${account.access_token}`,
25+
},
26+
}
27+
);
28+
29+
if (!res.ok) {
30+
console.error(
31+
`GitHub API returned an error: ${res.status} ${res.statusText}`
32+
);
33+
return false;
34+
}
35+
36+
const orgs = await res.json();
37+
38+
if (!Array.isArray(orgs)) {
39+
console.error("Unexpected GitHub API response:", orgs);
40+
return false;
41+
}
42+
43+
const isMember = orgs.some(
44+
(org) => org.login === process.env.GITHUB_ORG
45+
);
46+
47+
if (!isMember) {
48+
console.log(
49+
`Access denied: Not a member of the organization ${process.env.GITHUB_ORG}`
50+
);
51+
return false;
52+
}
53+
} catch (error) {
54+
console.error(
55+
"Error fetching GitHub organizations:",
56+
error
57+
);
58+
return false;
59+
}
60+
}
61+
62+
return true; // Allow login
63+
},
64+
async session({ session, token }) {
65+
session.user.id = token.id;
66+
return session;
67+
},
68+
async jwt({ token, user, account }) {
69+
if (account) {
70+
token.id = user.id;
71+
}
72+
return token;
73+
},
74+
},
75+
secret: process.env.NEXTAUTH_SECRET,
76+
};
77+
78+
export default NextAuth(authOptions);

src/pages/login.tsx

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,31 @@ import { useRouter } from "next/router";
33
import PageSeo from "@components/seo/page-seo";
44
import Layout from "@layout/layout-01";
55
import Breadcrumb from "@components/breadcrumb";
6-
import LoginForm from "@components/forms/login-form";
76
import Spinner from "@ui/spinner";
8-
import { useUser } from "@contexts/user-context";
97
import { useMount } from "@hooks";
108
import WelcomeMessage from "@components/welcome-message";
9+
import { useSession, signIn, signOut } from "next-auth/react";
1110

1211
const Login = () => {
1312
const mounted = useMount();
14-
const { isLoggedIn, logout } = useUser();
13+
const { data: session, status } = useSession();
1514
const router = useRouter();
1615

1716
useEffect(() => {
18-
if (isLoggedIn) {
19-
void router.push("/profile"); // Redirect to dashboard if already logged in
17+
if (status === "authenticated") {
18+
void router.push("/profile"); // Redirect to profile if logged in
2019
}
21-
}, [isLoggedIn, router]);
20+
}, [status, router]);
2221

23-
if (!mounted) return null;
22+
if (!mounted || status === "loading") {
23+
return (
24+
<div className="tw-fixed tw-bg-light-100 tw-top-0 tw-z-50 tw-w-screen tw-h-screen tw-flex tw-justify-center tw-items-center">
25+
<Spinner />
26+
</div>
27+
);
28+
}
2429

25-
if (!isLoggedIn) {
30+
if (!session) {
2631
return (
2732
<>
2833
<PageSeo title="Login" description="Login to your account" />
@@ -36,7 +41,12 @@ const Login = () => {
3641
<WelcomeMessage />
3742
</div>
3843
<div className="tw-flex tw-items-center tw-w-full lg:tw-w-3/4 tw-mx-auto">
39-
<LoginForm />
44+
<button
45+
onClick={() => signIn("github")}
46+
className="tw-bg-primary tw-text-white tw-py-2 tw-px-4 tw-rounded"
47+
>
48+
Sign in with GitHub
49+
</button>
4050
</div>
4151
</div>
4252
</>
@@ -46,7 +56,11 @@ const Login = () => {
4656
return (
4757
<div className="tw-fixed tw-bg-light-100 tw-top-0 tw-z-50 tw-w-screen tw-h-screen tw-flex tw-justify-center tw-items-center">
4858
<Spinner />
49-
<button type="button" onClick={logout}>
59+
<button
60+
type="button"
61+
onClick={() => signOut()}
62+
className="tw-bg-red-500 tw-text-white tw-py-2 tw-px-4 tw-rounded"
63+
>
5064
Logout
5165
</button>
5266
</div>
@@ -67,4 +81,4 @@ export const getStaticProps = () => {
6781
};
6882
};
6983

70-
export default Login;
84+
export default Login;

src/pages/profile.tsx

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,43 @@ import Layout01 from "@layout/layout-01";
66
import Breadcrumb from "@components/breadcrumb";
77
import ProfileBio from "@containers/profile/bio";
88
import Spinner from "@ui/spinner";
9-
import { useUser } from "@contexts/user-context";
10-
import { useMount } from "@hooks";
9+
import { useSession, signOut } from "next-auth/react";
1110

1211
type PageProps = NextPage & {
1312
Layout: typeof Layout01;
1413
};
1514

1615
const Profile: PageProps = () => {
17-
const mounted = useMount();
18-
const { isLoggedIn, logout } = useUser();
16+
const { data: session, status } = useSession();
1917
const router = useRouter();
2018

2119
useEffect(() => {
22-
if (!isLoggedIn) {
20+
if (status === "unauthenticated") {
21+
// Redirect to login if not logged in
2322
void router.push("/login");
2423
}
25-
}, [isLoggedIn, router]);
24+
}, [status, router]);
2625

27-
if (!mounted) return null;
28-
29-
if (!isLoggedIn) {
26+
if (status === "loading") {
27+
// Show a spinner while the session is being fetched
3028
return (
3129
<div className="tw-fixed tw-bg-light-100 tw-top-0 tw-z-50 tw-w-screen tw-h-screen tw-flex tw-justify-center tw-items-center">
3230
<Spinner />
3331
</div>
3432
);
3533
}
3634

37-
const handleLogout = () => {
38-
logout();
35+
if (!session) {
36+
// This shouldn't happen due to the redirect above, but handle the case
37+
return (
38+
<div className="tw-fixed tw-bg-light-100 tw-top-0 tw-z-50 tw-w-screen tw-h-screen tw-flex tw-justify-center tw-items-center">
39+
<p>You are not logged in.</p>
40+
</div>
41+
);
42+
}
43+
44+
const handleLogout = async () => {
45+
await signOut();
3946
void router.push("/login");
4047
};
4148

@@ -75,4 +82,4 @@ export const getStaticProps: GetStaticProps = () => {
7582
};
7683
};
7784

78-
export default Profile;
85+
export default Profile;

0 commit comments

Comments
 (0)