diff --git a/components.json b/components.json new file mode 100644 index 0000000..925efbf --- /dev/null +++ b/components.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "default", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "tailwind.config.ts", + "css": "src/styles/globals.css", + "baseColor": "slate", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "~/components", + "utils": "~/lib/utils" + } +} \ No newline at end of file diff --git a/next.config.js b/next.config.js index 9bfe4a0..29b4643 100644 --- a/next.config.js +++ b/next.config.js @@ -5,6 +5,15 @@ await import("./src/env.js"); /** @type {import("next").NextConfig} */ -const config = {}; +const config = { + images: { + remotePatterns: [ + { + protocol: "https", + hostname: "avatars.githubusercontent.com", + }, + ], + }, +}; export default config; diff --git a/package.json b/package.json index 2cc8974..9ad9ee3 100644 --- a/package.json +++ b/package.json @@ -15,14 +15,21 @@ }, "dependencies": { "@auth/drizzle-adapter": "^1.1.0", + "@radix-ui/react-slot": "^1.0.2", "@t3-oss/env-nextjs": "^0.10.1", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.1", "drizzle-orm": "^0.30.10", "geist": "^1.3.0", + "lucide-react": "^0.394.0", "next": "^14.2.1", "next-auth": "5.0.0-beta.19", "postgres": "^3.4.4", "react": "^18.3.0", "react-dom": "^18.3.0", + "react-icons": "^5.2.1", + "tailwind-merge": "^2.3.0", + "tailwindcss-animate": "^1.0.7", "zod": "^3.23.3" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7296966..4db68a5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,15 +11,27 @@ importers: '@auth/drizzle-adapter': specifier: ^1.1.0 version: 1.2.0 + '@radix-ui/react-slot': + specifier: ^1.0.2 + version: 1.0.2(@types/react@18.3.3)(react@18.3.1) '@t3-oss/env-nextjs': specifier: ^0.10.1 version: 0.10.1(typescript@5.4.5)(zod@3.23.8) + class-variance-authority: + specifier: ^0.7.0 + version: 0.7.0 + clsx: + specifier: ^2.1.1 + version: 2.1.1 drizzle-orm: specifier: ^0.30.10 version: 0.30.10(@types/react@18.3.3)(postgres@3.4.4)(react@18.3.1) geist: specifier: ^1.3.0 version: 1.3.0(next@14.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) + lucide-react: + specifier: ^0.394.0 + version: 0.394.0(react@18.3.1) next: specifier: ^14.2.1 version: 14.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -35,6 +47,15 @@ importers: react-dom: specifier: ^18.3.0 version: 18.3.1(react@18.3.1) + react-icons: + specifier: ^5.2.1 + version: 5.2.1(react@18.3.1) + tailwind-merge: + specifier: ^2.3.0 + version: 2.3.0 + tailwindcss-animate: + specifier: ^1.0.7 + version: 1.0.7(tailwindcss@3.4.3) zod: specifier: ^3.23.3 version: 3.23.8 @@ -518,6 +539,24 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} + '@radix-ui/react-compose-refs@1.0.1': + resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-slot@1.0.2': + resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@rushstack/eslint-patch@1.10.3': resolution: {integrity: sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==} @@ -809,6 +848,9 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + class-variance-authority@0.7.0: + resolution: {integrity: sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==} + cli-color@2.0.4: resolution: {integrity: sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==} engines: {node: '>=0.10'} @@ -816,6 +858,14 @@ packages: client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + clsx@2.0.0: + resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==} + engines: {node: '>=6'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -1595,6 +1645,11 @@ packages: lru-queue@0.1.0: resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==} + lucide-react@0.394.0: + resolution: {integrity: sha512-PzTbJ0bsyXRhH59k5qe7MpTd5MxlpYZUcM9kGSwvPGAfnn0J6FElDwu2EX6Vuh//F7y60rcVJiFQ7EK9DCMgfw==} + peerDependencies: + react: ^16.5.1 || ^17.0.0 || ^18.0.0 + memoizee@0.4.17: resolution: {integrity: sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==} engines: {node: '>=0.12'} @@ -1926,6 +1981,11 @@ packages: peerDependencies: react: ^18.3.1 + react-icons@5.2.1: + resolution: {integrity: sha512-zdbW5GstTzXaVKvGSyTaBalt7HSfuK5ovrzlpyiWHAFXndXTdd/1hdDHI4xBM1Mn7YriT6aqESucFl9kEXzrdw==} + peerDependencies: + react: '*' + react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} @@ -2109,6 +2169,14 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + tailwind-merge@2.3.0: + resolution: {integrity: sha512-vkYrLpIP+lgR0tQCG6AP7zZXCTLc1Lnv/CCRT3BqJ9CZ3ui2++GPaGb1x/ILsINIMSYqqvrpqjUFsMNLlW99EA==} + + tailwindcss-animate@1.0.7: + resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==} + peerDependencies: + tailwindcss: '>=3.0.0 || insiders' + tailwindcss@3.4.3: resolution: {integrity: sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==} engines: {node: '>=14.0.0'} @@ -2527,6 +2595,21 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true + '@radix-ui/react-compose-refs@1.0.1(@types/react@18.3.3)(react@18.3.1)': + dependencies: + '@babel/runtime': 7.24.6 + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.3 + + '@radix-ui/react-slot@1.0.2(@types/react@18.3.3)(react@18.3.1)': + dependencies: + '@babel/runtime': 7.24.6 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.3)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.3 + '@rushstack/eslint-patch@1.10.3': {} '@swc/counter@0.1.3': {} @@ -2878,6 +2961,10 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + class-variance-authority@0.7.0: + dependencies: + clsx: 2.0.0 + cli-color@2.0.4: dependencies: d: 1.0.2 @@ -2888,6 +2975,10 @@ snapshots: client-only@0.0.1: {} + clsx@2.0.0: {} + + clsx@2.1.1: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -3818,6 +3909,10 @@ snapshots: dependencies: es5-ext: 0.10.64 + lucide-react@0.394.0(react@18.3.1): + dependencies: + react: 18.3.1 + memoizee@0.4.17: dependencies: d: 1.0.2 @@ -4081,6 +4176,10 @@ snapshots: react: 18.3.1 scheduler: 0.23.2 + react-icons@5.2.1(react@18.3.1): + dependencies: + react: 18.3.1 + react-is@16.13.1: {} react@18.3.1: @@ -4286,6 +4385,14 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + tailwind-merge@2.3.0: + dependencies: + '@babel/runtime': 7.24.6 + + tailwindcss-animate@1.0.7(tailwindcss@3.4.3): + dependencies: + tailwindcss: 3.4.3 + tailwindcss@3.4.3: dependencies: '@alloc/quick-lru': 5.2.0 diff --git a/public/images/github-mark-white.svg b/public/images/github-mark-white.svg new file mode 100644 index 0000000..d5e6491 --- /dev/null +++ b/public/images/github-mark-white.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/wallpapers/faroe_islands.jpg b/public/images/wallpapers/faroe_islands.jpg new file mode 100644 index 0000000..411692a Binary files /dev/null and b/public/images/wallpapers/faroe_islands.jpg differ diff --git a/src/app/_components/auth/sign_in_gh.tsx b/src/app/_components/auth/sign_in_gh.tsx index 4d4d367..8f1dcdb 100644 --- a/src/app/_components/auth/sign_in_gh.tsx +++ b/src/app/_components/auth/sign_in_gh.tsx @@ -1,13 +1,49 @@ -import { signIn } from "~/auth" +import { signIn, signOut, auth } from "~/auth" +import Image from "next/image"; export async function SignInGH() { - return ( -
{ - "use server"; - await signIn("github"); - }}> - -
- ); + const session = await auth(); + if (session) { + return ( +
+
{ + "use server"; + await signOut(); + }}> + +
+
+ ); + } else { + return ( +
{ + "use server"; + await signIn("github"); + }}> + +
+ ); + } } diff --git a/src/app/_components/ui/dock.tsx b/src/app/_components/ui/dock.tsx new file mode 100644 index 0000000..ef5c24c --- /dev/null +++ b/src/app/_components/ui/dock.tsx @@ -0,0 +1,6 @@ +export function Dock() { + return ( +
+
+ ); +}; diff --git a/src/app/_components/ui/top_bar.tsx b/src/app/_components/ui/top_bar.tsx index 663b14b..e3c2d78 100644 --- a/src/app/_components/ui/top_bar.tsx +++ b/src/app/_components/ui/top_bar.tsx @@ -1,8 +1,31 @@ +import { SignInGH } from "~/app/_components/auth/sign_in_gh"; +import { GoDotFill } from "react-icons/go"; +import { CiPower } from "react-icons/ci"; +import { AiFillSound } from "react-icons/ai"; +import { FaNetworkWired } from "react-icons/fa"; +import { Button } from "~/components/ui/button"; export function Top_Bar() { return ( -
- +
+
+ +
+
+ +
+
+ +
); }; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index e4bfaa2..4c7f71d 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,8 +1,10 @@ import "~/styles/globals.css"; import { GeistSans } from "geist/font/sans"; import type { Metadata } from "next"; -import { Top_Bar } from "~/app/_components/ui/top_bar"; import { SessionProvider } from "next-auth/react"; +import { auth } from "~/auth"; +import { Top_Bar } from "~/app/_components/ui/top_bar"; +import { Dock } from "~/app/_components/ui/dock"; export const metadata: Metadata = { title: "Create T3 App", @@ -10,19 +12,33 @@ export const metadata: Metadata = { icons: [{ rel: "icon", url: "/favicon.ico" }], }; -export default function RootLayout({ +export default async function RootLayout({ children, }: { children: React.ReactNode; }) { - return ( - - - - - {children} - - - - ); + const session = await auth(); + if (!session) { + return ( + + + + {children} + + + + ); + } else { + return ( + + + + + {children} + < Dock /> + + + + ); + } } diff --git a/src/app/page.tsx b/src/app/page.tsx index 91430b2..3c05657 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,37 +1,27 @@ import Link from "next/link"; +import { auth } from "~/auth"; +import { SignInGH } from "~/app/_components/auth/sign_in_gh"; -export default function HomePage() { - return ( -
-
-

- Create T3 App -

-
- -

First Steps →

-
- Just the basics - Everything you need to know to set up your - database and authentication. -
- - -

Documentation →

-
- Learn more about Create T3 App, the libraries it uses, and how to - deploy it. -
- +export default async function HomePage() { + const session = await auth(); + if (!session) { + return ( +
+

+
+ {new Date().toDateString()}
-

-
- ); +
+ {new Date().toLocaleTimeString()} +
+ + < SignInGH /> + + ); + } else { + return ( +
+
+ ); + } } diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx new file mode 100644 index 0000000..d754ca0 --- /dev/null +++ b/src/components/ui/button.tsx @@ -0,0 +1,56 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "~/lib/utils" + +const buttonVariants = cva( + "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: + "border border-input bg-background hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-10 px-4 py-2", + sm: "h-9 rounded-md px-3", + lg: "h-11 rounded-md px-8", + icon: "h-10 w-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button" + return ( + + ) + } +) +Button.displayName = "Button" + +export { Button, buttonVariants } diff --git a/src/lib/utils.ts b/src/lib/utils.ts new file mode 100644 index 0000000..d084cca --- /dev/null +++ b/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { type ClassValue, clsx } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} diff --git a/src/styles/globals.css b/src/styles/globals.css index b5c61c9..ef0c11f 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -1,3 +1,90 @@ @tailwind base; @tailwind components; @tailwind utilities; + + @layer base { + :root { + --background: 222.2 84% 4.9%; + --foreground: 210 40% 98%; + + --card: 222.2 84% 4.9%; + --card-foreground: 210 40% 98%; + + --popover: 222.2 84% 4.9%; + --popover-foreground: 210 40% 98%; + + --primary: 210 40% 98%; + --primary-foreground: 222.2 47.4% 11.2%; + + --secondary: 217.2 32.6% 17.5%; + --secondary-foreground: 210 40% 98%; + + --muted: 217.2 32.6% 17.5%; + --muted-foreground: 215 20.2% 65.1%; + + --accent: 217.2 32.6% 17.5%; + --accent-foreground: 210 40% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 210 40% 98%; + + --border: 217.2 32.6% 17.5%; + --input: 217.2 32.6% 17.5%; + --ring: 212.7 26.8% 83.9%; + } + + .dark { + --background: 0 0% 100%; + --foreground: 222.2 84% 4.9%; + + --card: 0 0% 100%; + --card-foreground: 222.2 84% 4.9%; + + --popover: 0 0% 100%; + --popover-foreground: 222.2 84% 4.9%; + + --primary: 222.2 47.4% 11.2%; + --primary-foreground: 210 40% 98%; + + --secondary: 210 40% 96.1%; + --secondary-foreground: 222.2 47.4% 11.2%; + + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 46.9%; + + --accent: 210 40% 96.1%; + --accent-foreground: 222.2 47.4% 11.2%; + + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 210 40% 98%; + + --border: 214.3 31.8% 91.4%; + --input: 214.3 31.8% 91.4%; + --ring: 222.2 84% 4.9%; + + --radius: 0.5rem; + } + } + + @layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } + } + + html, body { + height: 100%; + margin: 0; + padding: 0; + } + + .backgrd { + background-image: url("/images/wallpapers/faroe_islands.jpg"); + background-size: cover; + background-position: center; + display: flex; + height: 100%; + } diff --git a/tailwind.config.ts b/tailwind.config.ts index 5fd44e8..84287e8 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,14 +1,80 @@ -import { type Config } from "tailwindcss"; -import { fontFamily } from "tailwindcss/defaultTheme"; +import type { Config } from "tailwindcss" -export default { - content: ["./src/**/*.tsx"], +const config = { + darkMode: ["class"], + content: [ + './pages/**/*.{ts,tsx}', + './components/**/*.{ts,tsx}', + './app/**/*.{ts,tsx}', + './src/**/*.{ts,tsx}', + ], + prefix: "", theme: { + container: { + center: true, + padding: "2rem", + screens: { + "2xl": "1400px", + }, + }, extend: { - fontFamily: { - sans: ["var(--font-geist-sans)", ...fontFamily.sans], + colors: { + border: "hsl(var(--border))", + input: "hsl(var(--input))", + ring: "hsl(var(--ring))", + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", + primary: { + DEFAULT: "hsl(var(--primary))", + foreground: "hsl(var(--primary-foreground))", + }, + secondary: { + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", + }, + destructive: { + DEFAULT: "hsl(var(--destructive))", + foreground: "hsl(var(--destructive-foreground))", + }, + muted: { + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))", + }, + accent: { + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", + }, + popover: { + DEFAULT: "hsl(var(--popover))", + foreground: "hsl(var(--popover-foreground))", + }, + card: { + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", + }, + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", + }, + keyframes: { + "accordion-down": { + from: { height: "0" }, + to: { height: "var(--radix-accordion-content-height)" }, + }, + "accordion-up": { + from: { height: "var(--radix-accordion-content-height)" }, + to: { height: "0" }, + }, + }, + animation: { + "accordion-down": "accordion-down 0.2s ease-out", + "accordion-up": "accordion-up 0.2s ease-out", }, }, }, - plugins: [], -} satisfies Config; + plugins: [require("tailwindcss-animate")], +} satisfies Config + +export default config \ No newline at end of file