diff --git a/apps/www/app/(www)/login/_components/Login.tsx b/apps/www/app/(www)/login/_components/Login.tsx new file mode 100644 index 00000000..a91f5287 --- /dev/null +++ b/apps/www/app/(www)/login/_components/Login.tsx @@ -0,0 +1,204 @@ +"use client"; +import { Input } from "@/components/ui/input"; +import { cn } from "@/lib/utils"; +import { signIn } from "next-auth/react"; +import { BottomLine } from "components/LineUtils"; +import { PlusSvg } from "components/SectionSvg"; +import { ChevronRight } from "lucide-react"; +import React, { useState } from "react"; + +export default function FUILoginWithGridProvider() { + const [reset, setReset] = useState(false); + return ( +
+
+ + + + + + +
+ +
+

+ Log in to your account +

+

+ Don't have an account?{" "} + + Sign up + +

+
+
+
+
+ + + {" "} +
+
+ +

+ Or continue with +

+
+
e.preventDefault()} className="space-y-5"> +
+ + +
+
+ + +
+ +
+
+ +
+
+
+ ); +} diff --git a/apps/www/app/(www)/login/page.tsx b/apps/www/app/(www)/login/page.tsx new file mode 100644 index 00000000..91736483 --- /dev/null +++ b/apps/www/app/(www)/login/page.tsx @@ -0,0 +1,61 @@ +import ChangelogDisplay from "components/Changelog/ChangelogDisplay"; +import RetroGrid from "components/ui/Grid"; +import { ChevronRight } from "lucide-react"; +import FUILoginWithGridProvider from "./_components/Login"; +import Section from "components/SectionView"; +import { BottomLine } from "components/LineUtils"; +import { getSession } from "next-auth/react"; +import { auth } from "auth"; +import { redirect } from "next/navigation"; +const { title, description }: { title: string; description: string } = { + title: "Login - Join FarmUI to grab exlusive perks.", + description: "Join the community to get fast and up to date informations", +}; + +export const metadata = { + metadataBase: new URL("https://farmui.com"), + title, + description, + openGraph: { + title, + description, + images: [ + { + url: "https://farmui.com/og.png", + }, + ], + url: "https://farmui.com", + }, + twitter: { + card: "summary_large_image", + title, + description, + images: ["https://farmui.com/og.png"], + creator: "@farmui", + }, +}; +const LogInPage = async () => { + const user = await auth() + if(user?.user) { + redirect("/") + } + return ( +
+
+ + +
+ +
+
+
+ ); +}; + +export default LogInPage; diff --git a/apps/www/app/(www)/templates/[slug]/page.tsx b/apps/www/app/(www)/templates/[slug]/page.tsx index 0051eb11..801d8051 100644 --- a/apps/www/app/(www)/templates/[slug]/page.tsx +++ b/apps/www/app/(www)/templates/[slug]/page.tsx @@ -55,7 +55,7 @@ const TemplatePage = async ({ params: { slug } }: { params: Params }) => { return ( <> -
+

diff --git a/apps/www/app/api/auth/[...nextauth]/route.ts b/apps/www/app/api/auth/[...nextauth]/route.ts new file mode 100644 index 00000000..fe509305 --- /dev/null +++ b/apps/www/app/api/auth/[...nextauth]/route.ts @@ -0,0 +1,2 @@ +import { handlers } from "../../../../auth"; // Referring to the auth.ts we just created +export const { GET, POST } = handlers; diff --git a/apps/www/app/layout.tsx b/apps/www/app/layout.tsx index 845a305f..2995a912 100644 --- a/apps/www/app/layout.tsx +++ b/apps/www/app/layout.tsx @@ -16,6 +16,7 @@ import { GeistMono } from "geist/font/mono"; import { Toaster } from "@/components/ui/toaster"; import Loglib from "@loglib/tracker/react"; import { Analytics } from "@vercel/analytics/react"; +import { SessionProvider } from "next-auth/react"; const { title, desc, ogImage } = metatag; export const metadata = { metadataBase: new URL("https://farmui.com"), @@ -85,31 +86,34 @@ export default function RootLayout({ - - + - -
{children}
- - -
- + + +
{children}
+ + +
+ + ); } diff --git a/apps/www/auth.ts b/apps/www/auth.ts new file mode 100644 index 00000000..dd367122 --- /dev/null +++ b/apps/www/auth.ts @@ -0,0 +1,6 @@ +import NextAuth from "next-auth"; +import Google from "next-auth/providers/google" + +export const { handlers, signIn, signOut, auth } = NextAuth({ + providers: [Google], +}); diff --git a/apps/www/components/ui/Hero/index.tsx b/apps/www/components/ui/Hero/index.tsx index 08ace018..30394b34 100644 --- a/apps/www/components/ui/Hero/index.tsx +++ b/apps/www/components/ui/Hero/index.tsx @@ -9,7 +9,9 @@ import HeroAnimated from "components/HeroAnimated"; import { cn } from "@/lib/utils"; import heroStyle from "components/HeroNit/hero.module.css"; import NumberTicker from "components/NumberCounter"; +import { signIn } from "../../../auth"; import bgback from "../../../public/bg-back.png"; + async function getGitHubStars() { try { const response = await fetch( @@ -94,6 +96,7 @@ export default async function () {

+
@@ -113,3 +116,16 @@ export default async function () { ); } + +export function SignIn() { + return ( +
{ + "use server"; + await signIn("google"); + }} + > + +
+ ); +} diff --git a/apps/www/components/ui/Navbar/JoinUs.tsx b/apps/www/components/ui/Navbar/JoinUs.tsx new file mode 100644 index 00000000..968c6f2c --- /dev/null +++ b/apps/www/components/ui/Navbar/JoinUs.tsx @@ -0,0 +1,43 @@ +import { ChevronRight, User } from "lucide-react"; +import LinkItem from "../LinkItem"; +import { auth } from "../../../auth"; +import { + TooltipProvider, + TooltipTrigger, + TooltipContent, + Tooltip, +} from "@/components/ui/tooltip"; +const JoinUs = async () => { + const user = await auth(); + console.log({user}) +// if (!!user?.user) { +// const extractedUser = user.user +// return ( +// +// +// +// {extractedUser.image ? ( +// + + +// ): ( +// +// )} +// +// +//

{user.user.name}

+//
+//
+//
+// ); +// } + return ( + <> + ); +}; + +export default JoinUs; diff --git a/apps/www/components/ui/Navbar/Navbar.tsx b/apps/www/components/ui/Navbar/Navbar.tsx index 22a50dfe..d9250c81 100644 --- a/apps/www/components/ui/Navbar/Navbar.tsx +++ b/apps/www/components/ui/Navbar/Navbar.tsx @@ -9,10 +9,18 @@ import NewsletterModal from "../NewsletterModal"; import { SparklesIcon } from "@heroicons/react/24/outline"; import { usePathname } from "next/navigation"; import { cn } from "@/lib/utils"; -import { ChevronRight } from "lucide-react"; +import { ChevronRight, User } from "lucide-react"; +import { useSession } from "next-auth/react"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; export default () => { const [state, setState] = useState(false); + const session = useSession(); const [isNewsletterModalActive, setNewsletterModalActive] = useState(false); const pathname = usePathname(); const navigation = [ @@ -21,8 +29,7 @@ export default () => { { title: "Demo", path: "/demo" }, { title: "Logs", path: "/changelog" }, - { title: "Join", path: "/join", - }, + { title: "Join", path: "/join" }, ]; useEffect(() => { document.onclick = (e) => { @@ -31,6 +38,8 @@ export default () => { }; }, []); + const user = session.data?.user; + function EditorWithAiButton() { return (
diff --git a/apps/www/db/schema.ts b/apps/www/db/schema.ts index dd6d06e7..13df4796 100644 --- a/apps/www/db/schema.ts +++ b/apps/www/db/schema.ts @@ -1,4 +1,4 @@ -import { pgTable, serial, text, doublePrecision } from 'drizzle-orm/pg-core'; +import { pgTable, serial, integer , text, doublePrecision , timestamp , index , uniqueIndex, primaryKey } from 'drizzle-orm/pg-core'; export var messages = pgTable("messages" , { id: serial('id').primaryKey(), @@ -14,3 +14,60 @@ export var subscribers = pgTable("subscribers" , { }) +export var users = pgTable("users", { + id: text("id").notNull().primaryKey(), + name: text("name"), + email: text("email").notNull(), + emailVerified: timestamp("emailVerified", { mode: "date" }), + image: text("image"), + createdAt: timestamp("created_at").notNull().defaultNow(), + updatedAt: timestamp("updated_at").notNull().defaultNow(), + }); + + export var accounts = pgTable( + "accounts", + { + userId: text("userId") + .notNull() + .references(() => users.id, { onDelete: "cascade" }), + type: text("type").notNull(), + provider: text("provider").notNull(), + providerAccountId: text("providerAccountId").notNull(), + refresh_token: text("refresh_token"), + access_token: text("access_token"), + expires_at: integer("expires_at"), + token_type: text("token_type"), + scope: text("scope"), + id_token: text("id_token"), + session_state: text("session_state"), + createdAt: timestamp("created_at").notNull().defaultNow(), + updatedAt: timestamp("updated_at").notNull().defaultNow(), + }, + (account) => ({ + compoundKey: primaryKey(account.provider, account.providerAccountId), + }) + ); + + export var sessions = pgTable("sessions", { + sessionToken: text("sessionToken").notNull().primaryKey(), + userId: text("userId") + .notNull() + .references(() => users.id, { onDelete: "cascade" }), + expires: timestamp("expires", { mode: "date" }).notNull(), + createdAt: timestamp("created_at").notNull().defaultNow(), + updatedAt: timestamp("updated_at").notNull().defaultNow(), + }); + + export var verificationTokens = pgTable( + "verificationToken", + { + identifier: text("identifier").notNull(), + token: text("token").notNull(), + expires: timestamp("expires", { mode: "date" }).notNull(), + createdAt: timestamp("created_at").notNull().defaultNow(), + updatedAt: timestamp("updated_at").notNull().defaultNow(), + }, + (token) => ({ + compoundKey: primaryKey(token.identifier, token.token), + }) + ); \ No newline at end of file diff --git a/apps/www/package.json b/apps/www/package.json index de07b084..e0aaff4b 100644 --- a/apps/www/package.json +++ b/apps/www/package.json @@ -13,7 +13,6 @@ "@babel/preset-react": "^7.18.6", "@heroicons/react": "^2.0.18", "@hookform/resolvers": "^3.6.0", - "@kinfe123/farm-ui": "workspace:1.0.4", "@loglib/tracker": "^0.8.0", "@neondatabase/serverless": "^0.9.3", "@next/third-parties": "^14.0.3", @@ -54,6 +53,7 @@ "lucide-react": "^0.378.0", "moment": "^2.29.4", "next": "14.0.3", + "next-auth": "5.0.0-beta.19", "next-contentlayer": "^0.3.2", "next-mdx-remote": "^3.0.8", "next-themes": "^0.2.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1f5f229c..c8381a1c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -48,9 +48,6 @@ importers: '@hookform/resolvers': specifier: ^3.6.0 version: 3.6.0(react-hook-form@7.51.5) - '@kinfe123/farm-ui': - specifier: workspace:1.0.4 - version: link:../../packages/cli '@loglib/tracker': specifier: ^0.8.0 version: 0.8.0(react@18.3.1) @@ -171,6 +168,9 @@ importers: next: specifier: 14.0.3 version: 14.0.3(@babel/core@7.24.6)(@opentelemetry/api@1.8.0)(react-dom@18.3.1)(react@18.3.1) + next-auth: + specifier: 5.0.0-beta.19 + version: 5.0.0-beta.19(next@14.0.3)(react@18.3.1) next-contentlayer: specifier: ^0.3.2 version: 0.3.4(contentlayer@0.3.4)(esbuild@0.21.4)(next@14.0.3)(react-dom@18.3.1)(react@18.3.1) @@ -444,6 +444,29 @@ packages: hasBin: true dev: false + /@auth/core@0.32.0: + resolution: {integrity: sha512-3+ssTScBd+1fd0/fscAyQN1tSygXzuhysuVVzB942ggU4mdfiTbv36P0ccVnExKWYJKvu3E2r3/zxXCCAmTOrg==} + peerDependencies: + '@simplewebauthn/browser': ^9.0.1 + '@simplewebauthn/server': ^9.0.2 + nodemailer: ^6.8.0 + peerDependenciesMeta: + '@simplewebauthn/browser': + optional: true + '@simplewebauthn/server': + optional: true + nodemailer: + optional: true + dependencies: + '@panva/hkdf': 1.1.1 + '@types/cookie': 0.6.0 + cookie: 0.6.0 + jose: 5.4.0 + oauth4webapi: 2.10.4 + preact: 10.11.3 + preact-render-to-string: 5.2.3(preact@10.11.3) + dev: false + /@babel/code-frame@7.12.11: resolution: {integrity: sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==} dependencies: @@ -3186,6 +3209,10 @@ packages: engines: {node: '>=14'} dev: false + /@panva/hkdf@1.1.1: + resolution: {integrity: sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==} + dev: false + /@pkgjs/parseargs@0.11.0: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -4174,6 +4201,10 @@ packages: resolution: {integrity: sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ==} dev: false + /@types/cookie@0.6.0: + resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + dev: false + /@types/debug@4.1.12: resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} dependencies: @@ -5539,6 +5570,11 @@ packages: /convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + /cookie@0.6.0: + resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} + engines: {node: '>= 0.6'} + dev: false + /copy-anything@3.0.5: resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} engines: {node: '>=12.13'} @@ -8373,6 +8409,10 @@ packages: resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} hasBin: true + /jose@5.4.0: + resolution: {integrity: sha512-6rpxTHPAQyWMb9A35BroFl1Sp0ST3DpPcm5EVIxZxdH+e0Hv9fwhyB3XLKFUcHNpdSDnETmBfuPPTTlYz5+USw==} + dev: false + /joycon@3.1.1: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} @@ -9770,6 +9810,27 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true + /next-auth@5.0.0-beta.19(next@14.0.3)(react@18.3.1): + resolution: {integrity: sha512-YHu1igcAxZPh8ZB7GIM93dqgY6gcAzq66FOhQFheAdOx1raxNcApt05nNyNCSB6NegSiyJ4XOPsaNow4pfDmsg==} + peerDependencies: + '@simplewebauthn/browser': ^9.0.1 + '@simplewebauthn/server': ^9.0.2 + next: ^14 || ^15.0.0-0 + nodemailer: ^6.6.5 + react: ^18.2.0 || ^19.0.0-0 + peerDependenciesMeta: + '@simplewebauthn/browser': + optional: true + '@simplewebauthn/server': + optional: true + nodemailer: + optional: true + dependencies: + '@auth/core': 0.32.0 + next: 14.0.3(@babel/core@7.24.6)(@opentelemetry/api@1.8.0)(react-dom@18.3.1)(react@18.3.1) + react: 18.3.1 + dev: false + /next-contentlayer@0.3.4(contentlayer@0.3.4)(esbuild@0.21.4)(next@14.0.3)(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-UtUCwgAl159KwfhNaOwyiI7Lg6sdioyKMeh+E7jxx0CJ29JuXGxBEYmCI6+72NxFGIFZKx8lvttbbQhbnYWYSw==} peerDependencies: @@ -9963,6 +10024,10 @@ packages: set-blocking: 2.0.0 dev: true + /oauth4webapi@2.10.4: + resolution: {integrity: sha512-DSoj8QoChzOCQlJkRmYxAJCIpnXFW32R0Uq7avyghIeB6iJq0XAblOD7pcq3mx4WEBDwMuKr0Y1qveCBleG2Xw==} + dev: false + /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -10518,6 +10583,19 @@ packages: engines: {node: '>=12'} dev: false + /preact-render-to-string@5.2.3(preact@10.11.3): + resolution: {integrity: sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==} + peerDependencies: + preact: '>=10' + dependencies: + preact: 10.11.3 + pretty-format: 3.8.0 + dev: false + + /preact@10.11.3: + resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==} + dev: false + /preferred-pm@3.1.3: resolution: {integrity: sha512-MkXsENfftWSRpzCzImcp4FRsCc3y1opwB73CfCNWyzMqArju2CrlMHlqB7VexKiPEOjGMbttv1r9fSCn5S610w==} engines: {node: '>=10'} @@ -10547,6 +10625,10 @@ packages: react-is: 17.0.2 dev: false + /pretty-format@3.8.0: + resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==} + dev: false + /pretty-ms@7.0.1: resolution: {integrity: sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==} engines: {node: '>=10'}