diff --git a/package-lock.json b/package-lock.json index 6bd8e40..f8f19ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,8 @@ "version": "0.1.0", "dependencies": { "@prisma/client": "^6.16.2", + "@radix-ui/react-avatar": "^1.1.10", + "@radix-ui/react-slot": "^1.2.3", "@tailwindcss/postcss": "^4.1.13", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", @@ -1058,6 +1060,152 @@ "@prisma/debug": "6.16.2" } }, + "node_modules/@radix-ui/react-avatar": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.10.tgz", + "integrity": "sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-is-hydrated": "0.1.0", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-is-hydrated": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz", + "integrity": "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==", + "license": "MIT", + "dependencies": { + "use-sync-external-store": "^1.5.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -1394,7 +1542,7 @@ "version": "19.1.13", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.13.tgz", "integrity": "sha512-hHkbU/eoO3EG5/MZkuFSKmYqPbSVk5byPFa3e7y/8TybHiLMACgI8seVYlicwk7H5K/rI2px9xrQp/C+AUDTiQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "csstype": "^3.0.2" @@ -1404,7 +1552,7 @@ "version": "19.1.9", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.9.tgz", "integrity": "sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==", - "dev": true, + "devOptional": true, "license": "MIT", "peerDependencies": { "@types/react": "^19.0.0" @@ -2535,7 +2683,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/damerau-levenshtein": { @@ -6477,6 +6625,15 @@ "punycode": "^2.1.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index bf0e1fb..d7b7027 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,8 @@ }, "dependencies": { "@prisma/client": "^6.16.2", + "@radix-ui/react-avatar": "^1.1.10", + "@radix-ui/react-slot": "^1.2.3", "@tailwindcss/postcss": "^4.1.13", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", diff --git a/public/placeholder.svg b/public/placeholder.svg new file mode 100644 index 0000000..faea08c --- /dev/null +++ b/public/placeholder.svg @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/src/app/globals.css b/src/app/globals.css index 7a3e99b..359bc22 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -3,11 +3,82 @@ @custom-variant dark (&:is(.dark *)); +:root { + --background: oklch(0.08 0 0); + --foreground: oklch(0.98 0 0); + --card: oklch(0.12 0 0); + --card-foreground: oklch(0.98 0 0); + --popover: oklch(0.12 0 0); + --popover-foreground: oklch(0.98 0 0); + --primary: oklch(0.7 0.15 280); + --primary-foreground: oklch(0.98 0 0); + --secondary: oklch(0.18 0 0); + --secondary-foreground: oklch(0.98 0 0); + --muted: oklch(0.15 0 0); + --muted-foreground: oklch(0.65 0 0); + --accent: oklch(0.7 0.15 280); + --accent-foreground: oklch(0.98 0 0); + --destructive: oklch(0.577 0.245 27.325); + --destructive-foreground: oklch(0.98 0 0); + --border: oklch(0.25 0 0); + --input: oklch(0.18 0 0); + --ring: oklch(0.7 0.15 280); + --chart-1: oklch(0.7 0.15 280); + --chart-2: oklch(0.6 0.12 200); + --chart-3: oklch(0.65 0.18 120); + --chart-4: oklch(0.75 0.2 60); + --chart-5: oklch(0.8 0.15 340); + --radius: 0.75rem; + --sidebar: oklch(0.12 0 0); + --sidebar-foreground: oklch(0.98 0 0); + --sidebar-primary: oklch(0.7 0.15 280); + --sidebar-primary-foreground: oklch(0.98 0 0); + --sidebar-accent: oklch(0.18 0 0); + --sidebar-accent-foreground: oklch(0.98 0 0); + --sidebar-border: oklch(0.25 0 0); + --sidebar-ring: oklch(0.7 0.15 280); + --font-inter: 'Inter', sans-serif; + --font-jetbrains-mono: 'JetBrains Mono', monospace; +} + +.dark { + --background: oklch(0.08 0 0); + --foreground: oklch(0.98 0 0); + --card: oklch(0.12 0 0); + --card-foreground: oklch(0.98 0 0); + --popover: oklch(0.12 0 0); + --popover-foreground: oklch(0.98 0 0); + --primary: oklch(0.7 0.15 280); + --primary-foreground: oklch(0.98 0 0); + --secondary: oklch(0.18 0 0); + --secondary-foreground: oklch(0.98 0 0); + --muted: oklch(0.15 0 0); + --muted-foreground: oklch(0.65 0 0); + --accent: oklch(0.7 0.15 280); + --accent-foreground: oklch(0.98 0 0); + --destructive: oklch(0.577 0.245 27.325); + --destructive-foreground: oklch(0.98 0 0); + --border: oklch(0.25 0 0); + --input: oklch(0.18 0 0); + --ring: oklch(0.7 0.15 280); + --chart-1: oklch(0.7 0.15 280); + --chart-2: oklch(0.6 0.12 200); + --chart-3: oklch(0.65 0.18 120); + --chart-4: oklch(0.75 0.2 60); + --chart-5: oklch(0.8 0.15 340); + --sidebar: oklch(0.12 0 0); + --sidebar-foreground: oklch(0.98 0 0); + --sidebar-primary: oklch(0.7 0.15 280); + --sidebar-primary-foreground: oklch(0.98 0 0); + --sidebar-accent: oklch(0.18 0 0); + --sidebar-accent-foreground: oklch(0.98 0 0); + --sidebar-border: oklch(0.25 0 0); + --sidebar-ring: oklch(0.7 0.15 280); +} + @theme inline { - --radius-sm: calc(var(--radius) - 4px); - --radius-md: calc(var(--radius) - 2px); - --radius-lg: var(--radius); - --radius-xl: calc(var(--radius) + 4px); + --font-sans: var(--font-inter); + --font-mono: var(--font-jetbrains-mono); --color-background: var(--background); --color-foreground: var(--foreground); --color-card: var(--card); @@ -23,6 +94,7 @@ --color-accent: var(--accent); --color-accent-foreground: var(--accent-foreground); --color-destructive: var(--destructive); + --color-destructive-foreground: var(--destructive-foreground); --color-border: var(--border); --color-input: var(--input); --color-ring: var(--ring); @@ -31,6 +103,10 @@ --color-chart-3: var(--chart-3); --color-chart-4: var(--chart-4); --color-chart-5: var(--chart-5); + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); --color-sidebar: var(--sidebar); --color-sidebar-foreground: var(--sidebar-foreground); --color-sidebar-primary: var(--sidebar-primary); @@ -41,80 +117,127 @@ --color-sidebar-ring: var(--sidebar-ring); } -:root { - --radius: 0.625rem; - --background: oklch(1 0 0); - --foreground: oklch(0.13 0.028 261.692); - --card: oklch(1 0 0); - --card-foreground: oklch(0.13 0.028 261.692); - --popover: oklch(1 0 0); - --popover-foreground: oklch(0.13 0.028 261.692); - --primary: oklch(0.21 0.034 264.665); - --primary-foreground: oklch(0.985 0.002 247.839); - --secondary: oklch(0.967 0.003 264.542); - --secondary-foreground: oklch(0.21 0.034 264.665); - --muted: oklch(0.967 0.003 264.542); - --muted-foreground: oklch(0.551 0.027 264.364); - --accent: oklch(0.967 0.003 264.542); - --accent-foreground: oklch(0.21 0.034 264.665); - --destructive: oklch(0.577 0.245 27.325); - --border: oklch(0.928 0.006 264.531); - --input: oklch(0.928 0.006 264.531); - --ring: oklch(0.707 0.022 261.325); - --chart-1: oklch(0.646 0.222 41.116); - --chart-2: oklch(0.6 0.118 184.704); - --chart-3: oklch(0.398 0.07 227.392); - --chart-4: oklch(0.828 0.189 84.429); - --chart-5: oklch(0.769 0.188 70.08); - --sidebar: oklch(0.985 0.002 247.839); - --sidebar-foreground: oklch(0.13 0.028 261.692); - --sidebar-primary: oklch(0.21 0.034 264.665); - --sidebar-primary-foreground: oklch(0.985 0.002 247.839); - --sidebar-accent: oklch(0.967 0.003 264.542); - --sidebar-accent-foreground: oklch(0.21 0.034 264.665); - --sidebar-border: oklch(0.928 0.006 264.531); - --sidebar-ring: oklch(0.707 0.022 261.325); -} - -.dark { - --background: oklch(0.13 0.028 261.692); - --foreground: oklch(0.985 0.002 247.839); - --card: oklch(0.21 0.034 264.665); - --card-foreground: oklch(0.985 0.002 247.839); - --popover: oklch(0.21 0.034 264.665); - --popover-foreground: oklch(0.985 0.002 247.839); - --primary: oklch(0.928 0.006 264.531); - --primary-foreground: oklch(0.21 0.034 264.665); - --secondary: oklch(0.278 0.033 256.848); - --secondary-foreground: oklch(0.985 0.002 247.839); - --muted: oklch(0.278 0.033 256.848); - --muted-foreground: oklch(0.707 0.022 261.325); - --accent: oklch(0.278 0.033 256.848); - --accent-foreground: oklch(0.985 0.002 247.839); - --destructive: oklch(0.704 0.191 22.216); - --border: oklch(1 0 0 / 10%); - --input: oklch(1 0 0 / 15%); - --ring: oklch(0.551 0.027 264.364); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); - --sidebar: oklch(0.21 0.034 264.665); - --sidebar-foreground: oklch(0.985 0.002 247.839); - --sidebar-primary: oklch(0.488 0.243 264.376); - --sidebar-primary-foreground: oklch(0.985 0.002 247.839); - --sidebar-accent: oklch(0.278 0.033 256.848); - --sidebar-accent-foreground: oklch(0.985 0.002 247.839); - --sidebar-border: oklch(1 0 0 / 10%); - --sidebar-ring: oklch(0.551 0.027 264.364); -} - @layer base { * { @apply border-border outline-ring/50; } body { @apply bg-background text-foreground; + background: + radial-gradient(circle at 20% 80%, rgba(120, 119, 198, 0.3) 0%, transparent 50%), + radial-gradient(circle at 80% 20%, rgba(255, 119, 198, 0.15) 0%, transparent 50%), + radial-gradient(circle at 40% 40%, rgba(120, 219, 255, 0.1) 0%, transparent 50%), + linear-gradient(135deg, #0a0a0a 0%, #1a0a2e 25%, #16213e 50%, #0f3460 75%, #0a0a0a 100%); + background-size: + 100% 100%, + 100% 100%, + 100% 100%, + 400% 400%; + animation: gradientShift 15s ease infinite; + position: relative; + } + + @keyframes gradientShift { + 0%, + 100% { + background-position: + 0% 0%, + 0% 0%, + 0% 0%, + 0% 50%; + } + 25% { + background-position: + 0% 0%, + 0% 0%, + 0% 0%, + 100% 50%; + } + 50% { + background-position: + 0% 0%, + 0% 0%, + 0% 0%, + 100% 100%; + } + 75% { + background-position: + 0% 0%, + 0% 0%, + 0% 0%, + 0% 100%; + } + } + + body::before { + content: ''; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-image: + radial-gradient(2px 2px at 20px 30px, rgba(255, 255, 255, 0.15), transparent), + radial-gradient(2px 2px at 40px 70px, rgba(255, 255, 255, 0.1), transparent), + radial-gradient(1px 1px at 90px 40px, rgba(255, 255, 255, 0.1), transparent), + radial-gradient(1px 1px at 130px 80px, rgba(255, 255, 255, 0.1), transparent), + radial-gradient(2px 2px at 160px 30px, rgba(255, 255, 255, 0.1), transparent); + background-repeat: repeat; + background-size: 200px 100px; + animation: sparkle 20s linear infinite; + pointer-events: none; + z-index: -1; + } + + @keyframes sparkle { + from { + transform: translateY(0px); + } + to { + transform: translateY(-100px); + } + } +} + +.glow-purple { + box-shadow: + 0 0 20px rgba(168, 85, 247, 0.4), + 0 0 40px rgba(168, 85, 247, 0.2), + 0 0 80px rgba(168, 85, 247, 0.1); +} + +.text-glow { + text-shadow: + 0 0 10px rgba(168, 85, 247, 0.5), + 0 0 20px rgba(168, 85, 247, 0.3), + 0 0 40px rgba(168, 85, 247, 0.1); +} + +.futuristic-grid { + background-image: + linear-gradient(rgba(120, 119, 198, 0.1) 1px, transparent 1px), + linear-gradient(90deg, rgba(120, 119, 198, 0.1) 1px, transparent 1px); + background-size: 60px 60px; + position: relative; +} + +.futuristic-grid::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: radial-gradient(circle at 50% 50%, rgba(120, 119, 198, 0.05) 0%, transparent 70%); + animation: pulse 4s ease-in-out infinite; +} + +@keyframes pulse { + 0%, + 100% { + opacity: 0.3; + } + 50% { + opacity: 0.8; } } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 85aeba5..614bbc8 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,9 +1,21 @@ import type { Metadata } from 'next' +import { Inter, JetBrains_Mono } from 'next/font/google' import './globals.css' +const inter = Inter({ + subsets: ['latin'], + variable: '--font-inter', +}) + +const jetbrainsMono = JetBrains_Mono({ + subsets: ['latin'], + variable: '--font-jetbrains-mono', +}) + export const metadata: Metadata = { - title: 'Code Showcase Studio', - description: 'Code Showcase Studio', + title: 'Code Showcase Studio - Platform Project Mahasiswa POLNES', + description: + 'Platform untuk memamerkan project-project dari mahasiswa Politeknik Negeri Samarinda', authors: [ { name: 'Klub Pemrograman TI POLNES', @@ -18,8 +30,8 @@ export default function RootLayout({ children: React.ReactNode }>) { return ( - -
{children} + + {children} ) } diff --git a/src/app/page.tsx b/src/app/page.tsx index 9811c85..c71bc43 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,13 +1,26 @@ -import styles from './page.module.css' +import CTASection from '@/features/landing/components/cta-section' +import Footer from '@/features/landing/components/footer' +import Header from '@/features/landing/components/header' +import HeroSection from '@/features/landing/components/hero-section' +import LeaderboardSection from '@/features/landing/components/leaderboard-section' +import TimelineSection from '@/features/landing/components/timeline-section' +// import { StatsSection } from '@/components/stats-section' +// import { FeaturesSection } from '@/components/features-section' -export default function Home() { +export default function HomePage() { return ( - <> -+ Bergabunglah dengan komunitas developer Klub Pemrograman TI POLNES dan mulai memamerkan + karya-karya terbaikmu. Dapatkan feedback, networking, dan kesempatan karir yang lebih + baik. +
+ +Gratis untuk semua mahasiswa POLNES • Tidak ada biaya tersembunyi
+
+ KPTI Project Platform
++ Bergabunglah dengan komunitas Klub Pemrograman TI POLNES. Showcase project terbaikmu, + dapatkan feedback, dan bersaing di leaderboard bulanan. +
+ ++ Dipercaya oleh 500+ mahasiswa + POLNES +
++ Kompetisi sehat antar developer. Leaderboard di-refresh setiap bulan. +
+by {project.author}
++ Leaderboard akan di-refresh pada tanggal 1 setiap bulannya +
++ Jelajahi karya-karya terbaru dari pengguna lainnya yang penuh inovasi +
+{project.author}
+{project.postedAt}
+{project.description}
+ +