mirror of
https://github.com/nihonbuzz/nihonbuzz-academy.git
synced 2026-01-25 21:18:45 +07:00
update aja
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
# LPK NihonBuzz Academy Ecosystem Blueprint 🇯🇵
|
||||
# LPK Nihonbuzz Academy Ecosystem Blueprint 🇯🇵
|
||||
|
||||
Dokumen ini merupakan cetak biru (blueprint) teknis mutakhir untuk seluruh ekosistem digital **LPK NihonBuzz**, yang dirancang sebagai platform pelatihan kerja terintegrasi, manajemen administrasi kantor (Buku Kantor), dan validasi sertifikasi kompetensi Bahasa Jepang.
|
||||
Dokumen ini merupakan cetak biru (blueprint) teknis mutakhir untuk seluruh ekosistem digital **LPK Nihonbuzz**, yang dirancang sebagai platform pelatihan kerja terintegrasi, manajemen administrasi kantor (Buku Kantor), dan validasi sertifikasi kompetensi Bahasa Jepang.
|
||||
|
||||
---
|
||||
|
||||
## 1. High-Level Architecture
|
||||
|
||||
Eksosistem LPK NihonBuzz terbagi menjadi dua entitas utama yang saling terintegrasi namun berjalan di infrastruktur yang dioptimalkan untuk kebutuhan masing-masing.
|
||||
Eksosistem LPK Nihonbuzz terbagi menjadi dua entitas utama yang saling terintegrasi namun berjalan di infrastruktur yang dioptimalkan untuk kebutuhan masing-masing.
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
|
||||
BIN
public/brand/wave-pattern-global.jpg
Normal file
BIN
public/brand/wave-pattern-global.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 MiB |
142
public/brand/wave-pattern-global.svg
Normal file
142
public/brand/wave-pattern-global.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 337 KiB |
@@ -60,6 +60,49 @@
|
||||
}
|
||||
}
|
||||
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-xl text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 h-11 px-6 shadow-sm;
|
||||
}
|
||||
.btn-sm {
|
||||
@apply h-9 rounded-md px-3 text-xs shadow-sm;
|
||||
}
|
||||
.btn-lg {
|
||||
@apply h-12 rounded-xl px-8 shadow-sm;
|
||||
}
|
||||
.btn-icon {
|
||||
@apply h-11 w-11 px-0 shadow-sm;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
@apply bg-primary text-primary-foreground shadow hover:bg-primary/90 dark:hover:bg-primary/80;
|
||||
}
|
||||
.btn-secondary {
|
||||
@apply bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80 dark:hover:bg-secondary/70;
|
||||
}
|
||||
.btn-outline {
|
||||
@apply border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent dark:hover:text-accent-foreground;
|
||||
}
|
||||
.btn-ghost {
|
||||
@apply shadow-none hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 dark:hover:text-foreground;
|
||||
}
|
||||
.btn-destructive {
|
||||
@apply bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90 dark:hover:bg-destructive/80;
|
||||
}
|
||||
.btn-link {
|
||||
@apply text-primary underline-offset-4 hover:underline shadow-none bg-transparent hover:bg-transparent;
|
||||
}
|
||||
|
||||
/* Glassmorphism Utilities */
|
||||
.card-glass {
|
||||
@apply bg-white/50 dark:bg-black/30 backdrop-blur-xl border border-white/40 dark:border-white/10 shadow-sm;
|
||||
}
|
||||
|
||||
.btn-glass {
|
||||
@apply border border-white/40 dark:border-white/10 bg-white/40 dark:bg-white/5 hover:bg-white/60 dark:hover:bg-white/10 backdrop-blur-md text-foreground shadow-sm;
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.bg-grid {
|
||||
background-size: 40px 40px;
|
||||
@@ -76,6 +119,13 @@
|
||||
mask-image: linear-gradient(180deg, white, rgba(255, 255, 255, 0));
|
||||
-webkit-mask-image: linear-gradient(180deg, white, rgba(255, 255, 255, 0));
|
||||
}
|
||||
|
||||
.bg-wave-global {
|
||||
background-color: transparent;
|
||||
background-image: url('/brand/wave-pattern-global.svg');
|
||||
background-repeat: repeat;
|
||||
background-size: 400px auto; /* Adjust scale as needed, 400px seems a good starting point for visibility */
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
@@ -96,4 +146,3 @@
|
||||
.plyr--video {
|
||||
@apply rounded-2xl overflow-hidden shadow-2xl;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ export default function CourseCard({
|
||||
{/* Hover Glow Effect */}
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-primary/10 via-orange-500/5 to-transparent blur-2xl opacity-0 group-hover:opacity-100 transition-opacity duration-500 rounded-3xl" />
|
||||
|
||||
<Card className="relative overflow-hidden bg-card/50 backdrop-blur-sm transition-all duration-500 border-border/50 group-hover:border-primary/30 shadow-sm group-hover:shadow-2xl group-hover:shadow-primary/5 group-hover:-translate-y-1 rounded-2xl">
|
||||
<Card className="relative overflow-hidden transition-all duration-500 group-hover:border-primary/50 group-hover:-translate-y-1 rounded-2xl">
|
||||
<div className="relative aspect-[16/9] overflow-hidden">
|
||||
<img
|
||||
src={thumbnail || "/brand/Nihonbuzz-Academy-Logo-Branding-Pattern-Landscape.png"}
|
||||
|
||||
@@ -30,7 +30,7 @@ const itemVariants: Variants = {
|
||||
|
||||
export function Hero() {
|
||||
return (
|
||||
<section className="relative min-h-screen flex flex-col items-center justify-center overflow-hidden w-full bg-background selection:bg-primary/30 selection:text-primary pt-20">
|
||||
<section className="relative min-h-screen flex flex-col items-center justify-center overflow-hidden w-full bg-background selection:bg-primary/30 selection:text-primary">
|
||||
{/* Background Gradients - Boosted for Light Mode using CSS variables */}
|
||||
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-[1000px] h-[600px] bg-primary/20 dark:bg-primary/10 blur-[120px] rounded-full opacity-[var(--hero-glow-opacity)] pointer-events-none" />
|
||||
<div className="absolute bottom-0 right-0 w-[800px] h-[800px] bg-blue-500/10 dark:bg-blue-500/5 blur-[150px] rounded-full opacity-[var(--hero-glow-opacity)] pointer-events-none" />
|
||||
@@ -45,7 +45,7 @@ export function Hero() {
|
||||
variants={containerVariants}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
className="relative z-10 container px-4 mx-auto flex flex-col items-center text-center gap-8"
|
||||
className="relative z-10 container px-4 mx-auto flex flex-col items-center text-center gap-8 pt-24 lg:pt-32"
|
||||
>
|
||||
<motion.div variants={itemVariants}>
|
||||
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full border border-primary/10 bg-primary/5 backdrop-blur-sm shadow-inner text-sm text-primary font-bold mb-6">
|
||||
|
||||
91
resources/js/Components/Landing/Hero.tsx.bak
Normal file
91
resources/js/Components/Landing/Hero.tsx.bak
Normal file
@@ -0,0 +1,91 @@
|
||||
"use client";
|
||||
|
||||
import { motion, Variants } from "framer-motion";
|
||||
import { ArrowRight, Sparkles } from "lucide-react";
|
||||
import { Button } from "@/Components/ui/button";
|
||||
import { Link } from "@inertiajs/react";
|
||||
|
||||
const containerVariants: Variants = {
|
||||
hidden: { opacity: 0 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
transition: {
|
||||
staggerChildren: 0.2,
|
||||
delayChildren: 0.3,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const itemVariants: Variants = {
|
||||
hidden: { y: 20, opacity: 0 },
|
||||
visible: {
|
||||
y: 0,
|
||||
opacity: 1,
|
||||
transition: {
|
||||
duration: 0.8,
|
||||
ease: [0.215, 0.610, 0.355, 1.000],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export function Hero() {
|
||||
return (
|
||||
<section className="relative min-h-screen flex flex-col items-center justify-center overflow-hidden w-full bg-background selection:bg-primary/30 selection:text-primary pt-20">
|
||||
{/* Background Gradients - Boosted for Light Mode using CSS variables */}
|
||||
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-[1000px] h-[600px] bg-primary/20 dark:bg-primary/10 blur-[120px] rounded-full opacity-[var(--hero-glow-opacity)] pointer-events-none" />
|
||||
<div className="absolute bottom-0 right-0 w-[800px] h-[800px] bg-blue-500/10 dark:bg-blue-500/5 blur-[150px] rounded-full opacity-[var(--hero-glow-opacity)] pointer-events-none" />
|
||||
|
||||
{/* Grid Pattern Overlay */}
|
||||
<div className="absolute inset-0 bg-grid z-0" />
|
||||
|
||||
{/* Japanese Wave Pattern - Adjusted Opacity */}
|
||||
<div className="absolute inset-0 bg-seigaiha z-0 opacity-80 dark:opacity-40" />
|
||||
|
||||
<motion.div
|
||||
variants={containerVariants}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
className="relative z-10 container px-4 mx-auto flex flex-col items-center text-center gap-8"
|
||||
>
|
||||
<motion.div variants={itemVariants}>
|
||||
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full border border-primary/10 bg-primary/5 backdrop-blur-sm shadow-inner text-sm text-primary font-bold mb-6">
|
||||
<Sparkles className="w-4 h-4" />
|
||||
<span>Pendaftaran Batch 2026 Dibuka!</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
<motion.h1
|
||||
variants={itemVariants}
|
||||
className="text-5xl md:text-7xl lg:text-8xl font-black tracking-tight text-foreground leading-[1.1]"
|
||||
>
|
||||
Hubungkan Impianmu <br />
|
||||
<span className="text-transparent bg-clip-text bg-gradient-to-r from-primary via-primary/80 to-primary/40 italic">
|
||||
Ke Negeri Sakura
|
||||
</span>
|
||||
</motion.h1>
|
||||
|
||||
<motion.p
|
||||
variants={itemVariants}
|
||||
className="max-w-2xl text-lg md:text-xl text-muted-foreground leading-relaxed font-medium"
|
||||
>
|
||||
Platform edukasi terdepan untuk penguasaan Bahasa Jepang & karir profesional.
|
||||
Belajar JLPT N5 hingga N2 dengan kurikulum modern dan Spaced Repetition System.
|
||||
</motion.p>
|
||||
|
||||
<motion.div variants={itemVariants} className="flex flex-col sm:flex-row gap-5 mt-4">
|
||||
<Button asChild size="lg" className="rounded-full bg-primary hover:bg-primary/90 text-white min-w-[180px] h-14 shadow-xl shadow-primary/20 font-bold text-lg">
|
||||
<Link href={route('register')}>
|
||||
Mulai Belajar Gratis
|
||||
<ArrowRight className="w-5 h-5 ml-2" />
|
||||
</Link>
|
||||
</Button>
|
||||
<Button asChild size="lg" variant="outline" className="rounded-full border-border hover:bg-muted min-w-[180px] h-14 font-bold text-lg text-foreground">
|
||||
<Link href="#programs">
|
||||
Lihat Program
|
||||
</Link>
|
||||
</Button>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -39,7 +39,7 @@ export function Navbar() {
|
||||
className={cn(
|
||||
"flex items-center justify-between transition-all duration-300 ease-in-out pointer-events-auto",
|
||||
scrolled
|
||||
? "bg-background/80 backdrop-blur-xl border border-white/10 shadow-2xl w-full max-w-5xl px-10 py-3 rounded-full gap-8"
|
||||
? "bg-background/80 backdrop-blur-xl border border-white/10 shadow-none w-full max-w-5xl px-10 py-3 rounded-full gap-8"
|
||||
: "bg-transparent border-transparent w-full max-w-6xl px-6 py-3 rounded-full"
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -9,7 +9,7 @@ const Card = React.forwardRef<
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"rounded-xl border bg-card text-card-foreground shadow",
|
||||
"rounded-xl border border-white/40 dark:border-white/10 bg-white/50 dark:bg-black/30 backdrop-blur-xl text-card-foreground shadow-none",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -4,7 +4,7 @@ import React from "react";
|
||||
|
||||
export default function AuthLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<ThemeProvider defaultTheme="dark" storageKey="nihonbuzz-theme">
|
||||
<ThemeProvider defaultTheme="dark" storageKey="nihonbuzz-academy-theme">
|
||||
<div className="min-h-screen bg-background relative overflow-hidden flex items-center justify-center p-4">
|
||||
{/* Background Decorations - Pure CSS */}
|
||||
<div className="absolute inset-0 z-0">
|
||||
|
||||
@@ -2,12 +2,29 @@ import { ThemeProvider } from "@/Components/ThemeProvider";
|
||||
import { Navbar } from "@/Components/Landing/Navbar";
|
||||
import { Footer } from "@/Components/Landing/Footer";
|
||||
|
||||
export default function GuestLayout({ children }: { children: React.ReactNode }) {
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export default function GuestLayout({
|
||||
children,
|
||||
variant = 'default'
|
||||
}: {
|
||||
children: React.ReactNode,
|
||||
variant?: 'default' | 'landing'
|
||||
}) {
|
||||
return (
|
||||
<ThemeProvider defaultTheme="dark" storageKey="nihonbuzz-theme">
|
||||
<div className="min-h-screen bg-background text-foreground selection:bg-primary/30 selection:text-primary">
|
||||
<ThemeProvider defaultTheme="dark" storageKey="nihonbuzz-academy-theme">
|
||||
<div className="min-h-screen flex flex-col bg-background text-foreground selection:bg-primary/30 selection:text-primary relative isolate">
|
||||
{/* Global Background Pattern */}
|
||||
{/* SVG is white by default. In light mode, we invert it to black to be visible on white bg. */}
|
||||
<div className="fixed inset-0 z-[-1] bg-wave-global invert dark:invert-0 opacity-20 dark:opacity-5 pointer-events-none" />
|
||||
|
||||
<Navbar />
|
||||
<main>{children}</main>
|
||||
<main className={cn(
|
||||
"min-h-screen flex flex-col items-center justify-center overflow-hidden relative",
|
||||
variant === 'default' ? "pt-20 lg:pt-24 px-4" : "pt-0 px-0"
|
||||
)}>
|
||||
{children}
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
|
||||
@@ -24,33 +24,34 @@ export default function ConfirmPassword() {
|
||||
<Head title="Confirm Password" />
|
||||
|
||||
<div className="flex flex-col items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div className="w-full max-w-md bg-white p-8 rounded-3xl shadow-2xl border border-gray-100">
|
||||
<div className="mb-6 text-sm text-gray-600 dark:text-gray-400">
|
||||
This is a secure area of the application. Please confirm your
|
||||
password before continuing.
|
||||
<div className="w-full max-w-md">
|
||||
<div className="card-glass rounded-3xl p-8">
|
||||
<div className="mb-6 text-sm text-gray-600 dark:text-gray-400">
|
||||
This is a secure area of the application. Please confirm your
|
||||
password before continuing.
|
||||
</div>
|
||||
|
||||
<form onSubmit={submit} className="space-y-6">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="password">Password</Label>
|
||||
<Input
|
||||
id="password"
|
||||
type="password"
|
||||
name="password"
|
||||
value={data.password}
|
||||
className="block w-full"
|
||||
onChange={(e) => setData('password', e.target.value)}
|
||||
/>
|
||||
<InputError message={errors.password} />
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-end">
|
||||
<button className="btn btn-primary w-full h-auto py-3 rounded-xl shadow-sm font-bold text-white" disabled={processing}>
|
||||
Confirm
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<form onSubmit={submit} className="space-y-6">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="password">Password</Label>
|
||||
<Input
|
||||
id="password"
|
||||
type="password"
|
||||
name="password"
|
||||
value={data.password}
|
||||
className="block w-full"
|
||||
|
||||
onChange={(e) => setData('password', e.target.value)}
|
||||
/>
|
||||
<InputError message={errors.password} />
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-end">
|
||||
<Button className="w-full bg-nihonbuzz-red hover:bg-nihonbuzz-red/90 text-white font-bold py-3 rounded-xl" disabled={processing}>
|
||||
Confirm
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</GuestLayout>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { FormEventHandler } from 'react';
|
||||
import { Button } from '@/Components/ui/button';
|
||||
import { Input } from '@/Components/ui/input';
|
||||
import { Label } from '@/Components/ui/label';
|
||||
import { Card } from '@/Components/ui/card';
|
||||
|
||||
export default function ForgotPassword({ status }: { status?: string }) {
|
||||
const { data, setData, post, processing, errors } = useForm({
|
||||
@@ -22,7 +23,7 @@ export default function ForgotPassword({ status }: { status?: string }) {
|
||||
<Head title="Forgot Password" />
|
||||
|
||||
<div className="flex flex-col items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div className="w-full max-w-md bg-white p-8 rounded-3xl shadow-2xl border border-gray-100">
|
||||
<Card className="w-full max-w-md rounded-3xl overflow-hidden p-8">
|
||||
<div className="mb-6 text-sm text-gray-600 dark:text-gray-400">
|
||||
Forgot your password? No problem. Just let us know your email
|
||||
address and we will email you a password reset link that will
|
||||
@@ -51,12 +52,12 @@ export default function ForgotPassword({ status }: { status?: string }) {
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-end">
|
||||
<Button className="w-full bg-nihonbuzz-red hover:bg-nihonbuzz-red/90 text-white font-bold py-3 rounded-xl" disabled={processing}>
|
||||
<button className="btn btn-primary w-full h-auto py-3 rounded-xl shadow-sm font-bold text-white" disabled={processing}>
|
||||
Email Password Reset Link
|
||||
</Button>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</GuestLayout>
|
||||
);
|
||||
|
||||
@@ -34,7 +34,7 @@ export default function Login({
|
||||
<Head title="Log in" />
|
||||
|
||||
<div className="flex flex-col items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
|
||||
<Card className="w-full max-w-md border-gray-100 shadow-2xl rounded-3xl overflow-hidden">
|
||||
<Card className="w-full max-w-md rounded-3xl overflow-hidden">
|
||||
<CardHeader className="space-y-1 text-center pt-8">
|
||||
<CardTitle className="text-3xl font-extrabold tracking-tight">Selamat Datang Kembali</CardTitle>
|
||||
<CardDescription className="text-gray-500">
|
||||
@@ -101,9 +101,9 @@ export default function Login({
|
||||
</div>
|
||||
|
||||
<div className="pt-2">
|
||||
<Button className="w-full py-6 rounded-2xl text-base font-bold shadow-lg shadow-nihonbuzz-red/20 bg-nihonbuzz-red hover:bg-nihonbuzz-red/90" disabled={processing}>
|
||||
<button className="btn btn-primary w-full h-auto py-3 rounded-xl shadow-sm text-sm font-bold" disabled={processing}>
|
||||
Masuk Sekarang
|
||||
</Button>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="relative">
|
||||
@@ -119,7 +119,7 @@ export default function Login({
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
className="w-full py-6 rounded-2xl text-sm font-bold border-gray-100 hover:bg-gray-50 flex items-center justify-center gap-3 transition-all"
|
||||
className="btn btn-glass w-full h-auto py-3 rounded-xl text-sm font-bold flex items-center justify-center gap-3 transition-all"
|
||||
onClick={() => window.location.href = route('social.redirect', { provider: 'google' })}
|
||||
>
|
||||
<svg className="w-5 h-5" viewBox="0 0 24 24">
|
||||
|
||||
@@ -28,7 +28,7 @@ export default function Register() {
|
||||
<Head title="Register" />
|
||||
|
||||
<div className="flex flex-col items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
|
||||
<Card className="w-full max-w-md border-gray-100 shadow-2xl rounded-3xl overflow-hidden">
|
||||
<Card className="w-full max-w-md rounded-3xl overflow-hidden">
|
||||
<CardHeader className="space-y-1 text-center pt-8">
|
||||
<CardTitle className="text-3xl font-extrabold tracking-tight">Buat Akun Baru</CardTitle>
|
||||
<CardDescription className="text-gray-500">
|
||||
@@ -101,9 +101,9 @@ export default function Register() {
|
||||
</div>
|
||||
|
||||
<div className="pt-2">
|
||||
<Button className="w-full py-6 rounded-2xl text-base font-bold shadow-lg shadow-nihonbuzz-red/20 bg-nihonbuzz-red hover:bg-nihonbuzz-red/90" disabled={processing}>
|
||||
<button className="btn btn-primary w-full h-auto py-3 rounded-xl shadow-sm text-sm font-bold" disabled={processing}>
|
||||
Daftar Sekarang
|
||||
</Button>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="text-center text-sm text-gray-500">
|
||||
|
||||
@@ -33,58 +33,59 @@ export default function ResetPassword({
|
||||
<Head title="Reset Password" />
|
||||
|
||||
<div className="flex flex-col items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div className="w-full max-w-md bg-white p-8 rounded-3xl shadow-2xl border border-gray-100">
|
||||
<h2 className="text-2xl font-bold mb-6 text-center">Reset Password</h2>
|
||||
|
||||
<form onSubmit={submit} className="space-y-6">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="email">Email</Label>
|
||||
<Input
|
||||
id="email"
|
||||
type="email"
|
||||
name="email"
|
||||
value={data.email}
|
||||
className="block w-full"
|
||||
autoComplete="username"
|
||||
onChange={(e) => setData('email', e.target.value)}
|
||||
/>
|
||||
<InputError message={errors.email} />
|
||||
</div>
|
||||
<div className="w-full max-w-md">
|
||||
<div className="card-glass rounded-3xl p-8">
|
||||
<h2 className="text-2xl font-bold mb-6 text-center">Reset Password</h2>
|
||||
|
||||
<form onSubmit={submit} className="space-y-6">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="email">Email</Label>
|
||||
<Input
|
||||
id="email"
|
||||
type="email"
|
||||
name="email"
|
||||
value={data.email}
|
||||
className="block w-full"
|
||||
autoComplete="username"
|
||||
onChange={(e) => setData('email', e.target.value)}
|
||||
/>
|
||||
<InputError message={errors.email} />
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="password">Password</Label>
|
||||
<Input
|
||||
id="password"
|
||||
type="password"
|
||||
name="password"
|
||||
value={data.password}
|
||||
className="block w-full"
|
||||
autoComplete="new-password"
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="password">Password</Label>
|
||||
<Input
|
||||
id="password"
|
||||
type="password"
|
||||
name="password"
|
||||
value={data.password}
|
||||
className="block w-full"
|
||||
autoComplete="new-password"
|
||||
onChange={(e) => setData('password', e.target.value)}
|
||||
/>
|
||||
<InputError message={errors.password} />
|
||||
</div>
|
||||
|
||||
onChange={(e) => setData('password', e.target.value)}
|
||||
/>
|
||||
<InputError message={errors.password} />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="password_confirmation">Confirm Password</Label>
|
||||
<Input
|
||||
type="password"
|
||||
name="password_confirmation"
|
||||
value={data.password_confirmation}
|
||||
className="block w-full"
|
||||
autoComplete="new-password"
|
||||
onChange={(e) => setData('password_confirmation', e.target.value)}
|
||||
/>
|
||||
<InputError message={errors.password_confirmation} />
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="password_confirmation">Confirm Password</Label>
|
||||
<Input
|
||||
type="password"
|
||||
name="password_confirmation"
|
||||
value={data.password_confirmation}
|
||||
className="block w-full"
|
||||
autoComplete="new-password"
|
||||
onChange={(e) => setData('password_confirmation', e.target.value)}
|
||||
/>
|
||||
<InputError message={errors.password_confirmation} />
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-end">
|
||||
<Button className="w-full bg-nihonbuzz-red hover:bg-nihonbuzz-red/90 text-white font-bold py-3 rounded-xl" disabled={processing}>
|
||||
Reset Password
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
<div className="flex items-center justify-end">
|
||||
<button className="btn btn-primary w-full h-auto py-3 rounded-xl shadow-sm font-bold text-white" disabled={processing}>
|
||||
Reset Password
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</GuestLayout>
|
||||
|
||||
@@ -2,6 +2,7 @@ import GuestLayout from '@/Layouts/GuestLayout';
|
||||
import { Head, Link, useForm } from '@inertiajs/react';
|
||||
import { FormEventHandler } from 'react';
|
||||
import { Button } from '@/Components/ui/button';
|
||||
import { Card } from '@/Components/ui/card';
|
||||
|
||||
export default function VerifyEmail({ status }: { status?: string }) {
|
||||
const { post, processing } = useForm({});
|
||||
@@ -17,7 +18,7 @@ export default function VerifyEmail({ status }: { status?: string }) {
|
||||
<Head title="Email Verification" />
|
||||
|
||||
<div className="flex flex-col items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div className="w-full max-w-md bg-white p-8 rounded-3xl shadow-2xl border border-gray-100 text-center">
|
||||
<Card className="w-full max-w-md rounded-3xl overflow-hidden p-8 text-center">
|
||||
<div className="mb-6 text-sm text-gray-600 dark:text-gray-400">
|
||||
Thanks for signing up! Before getting started, could you verify
|
||||
your email address by clicking on the link we just emailed to
|
||||
@@ -33,9 +34,9 @@ export default function VerifyEmail({ status }: { status?: string }) {
|
||||
)}
|
||||
|
||||
<form onSubmit={submit} className="space-y-4">
|
||||
<Button className="w-full bg-nihonbuzz-red hover:bg-nihonbuzz-red/90 text-white font-bold py-3 rounded-xl" disabled={processing}>
|
||||
<button className="btn btn-primary w-full h-auto py-3 rounded-xl shadow-sm font-bold text-white" disabled={processing}>
|
||||
Resend Verification Email
|
||||
</Button>
|
||||
</button>
|
||||
|
||||
<Link
|
||||
href={route('logout')}
|
||||
@@ -46,7 +47,7 @@ export default function VerifyEmail({ status }: { status?: string }) {
|
||||
Log Out
|
||||
</Link>
|
||||
</form>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</GuestLayout>
|
||||
);
|
||||
|
||||
@@ -57,7 +57,7 @@ export default function Dashboard({
|
||||
<div className="space-y-8 animate-in fade-in duration-700">
|
||||
{/* Stats Grid */}
|
||||
<div className="grid gap-4 grid-cols-2 lg:grid-cols-4">
|
||||
<Card className="border-border/50 bg-card/50 backdrop-blur-sm">
|
||||
<Card className="shadow-none">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-[10px] font-bold uppercase tracking-wider text-muted-foreground">Total XP</CardTitle>
|
||||
<Trophy className="h-4 w-4 text-yellow-500" />
|
||||
@@ -66,7 +66,7 @@ export default function Dashboard({
|
||||
<div className="text-2xl font-black">{stats.xp_points.toLocaleString()}</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card className="border-border/50 bg-card/50 backdrop-blur-sm">
|
||||
<Card className="shadow-none">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-[10px] font-bold uppercase tracking-wider text-muted-foreground">Streak</CardTitle>
|
||||
<Flame className="h-4 w-4 text-orange-500" />
|
||||
@@ -75,7 +75,7 @@ export default function Dashboard({
|
||||
<div className="text-2xl font-black">{stats.current_streak} Hari</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card className="border-border/50 bg-card/50 backdrop-blur-sm">
|
||||
<Card className="shadow-none">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-[10px] font-bold uppercase tracking-wider text-muted-foreground">Kursus</CardTitle>
|
||||
<BookOpen className="h-4 w-4 text-blue-500" />
|
||||
@@ -84,7 +84,7 @@ export default function Dashboard({
|
||||
<div className="text-2xl font-black">{stats.active_courses} Aktif</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card className="border-border/50 bg-card/50 backdrop-blur-sm">
|
||||
<Card className="shadow-none">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-[10px] font-bold uppercase tracking-wider text-muted-foreground">Sertifikat</CardTitle>
|
||||
<GraduationCap className="h-4 w-4 text-green-500" />
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Hero } from '@/Components/Landing/Hero';
|
||||
|
||||
export default function Welcome({ auth }: PageProps) {
|
||||
return (
|
||||
<GuestLayout>
|
||||
<GuestLayout variant="landing">
|
||||
<Head title="Ecosystem Belajar Bahasa Jepang Modern" />
|
||||
<Hero />
|
||||
</GuestLayout>
|
||||
|
||||
@@ -19,7 +19,7 @@ createInertiaApp({
|
||||
const root = createRoot(el);
|
||||
|
||||
root.render(
|
||||
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
|
||||
<ThemeProvider defaultTheme="dark" storageKey="nihonbuzz-academy-theme">
|
||||
<App {...props} />
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
||||
@@ -30,6 +30,20 @@
|
||||
<meta name="msapplication-TileImage" content="/ms-icon-144x144.png">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
const storageKey = 'nihonbuzz-academy-theme';
|
||||
const theme = localStorage.getItem(storageKey);
|
||||
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
||||
|
||||
if (theme === 'dark' || (!theme && systemTheme === 'dark')) {
|
||||
document.documentElement.classList.add('dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
<!-- Scripts -->
|
||||
@routes
|
||||
@viteReactRefresh
|
||||
|
||||
91
tmp_hero_first.tsx
Normal file
91
tmp_hero_first.tsx
Normal file
@@ -0,0 +1,91 @@
|
||||
"use client";
|
||||
|
||||
import { motion, Variants } from "framer-motion";
|
||||
import { ArrowRight, Sparkles } from "lucide-react";
|
||||
import { Button } from "@/Components/ui/button";
|
||||
import { Link } from "@inertiajs/react";
|
||||
|
||||
const containerVariants: Variants = {
|
||||
hidden: { opacity: 0 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
transition: {
|
||||
staggerChildren: 0.2,
|
||||
delayChildren: 0.3,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const itemVariants: Variants = {
|
||||
hidden: { y: 20, opacity: 0 },
|
||||
visible: {
|
||||
y: 0,
|
||||
opacity: 1,
|
||||
transition: {
|
||||
duration: 0.8,
|
||||
ease: [0.215, 0.610, 0.355, 1.000],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export function Hero() {
|
||||
return (
|
||||
<section className="relative min-h-screen flex flex-col items-center justify-center overflow-hidden w-full bg-background selection:bg-primary/30 selection:text-primary pt-20">
|
||||
{/* Background Gradients - Boosted for Light Mode using CSS variables */}
|
||||
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-[1000px] h-[600px] bg-primary/20 dark:bg-primary/10 blur-[120px] rounded-full opacity-[var(--hero-glow-opacity)] pointer-events-none" />
|
||||
<div className="absolute bottom-0 right-0 w-[800px] h-[800px] bg-blue-500/10 dark:bg-blue-500/5 blur-[150px] rounded-full opacity-[var(--hero-glow-opacity)] pointer-events-none" />
|
||||
|
||||
{/* Grid Pattern Overlay */}
|
||||
<div className="absolute inset-0 bg-grid z-0" />
|
||||
|
||||
{/* Japanese Wave Pattern - Adjusted Opacity */}
|
||||
<div className="absolute inset-0 bg-seigaiha z-0 opacity-80 dark:opacity-40" />
|
||||
|
||||
<motion.div
|
||||
variants={containerVariants}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
className="relative z-10 container px-4 mx-auto flex flex-col items-center text-center gap-8"
|
||||
>
|
||||
<motion.div variants={itemVariants}>
|
||||
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full border border-primary/10 bg-primary/5 backdrop-blur-sm shadow-inner text-sm text-primary font-bold mb-6">
|
||||
<Sparkles className="w-4 h-4" />
|
||||
<span>Pendaftaran Batch 2026 Dibuka!</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
<motion.h1
|
||||
variants={itemVariants}
|
||||
className="text-5xl md:text-7xl lg:text-8xl font-black tracking-tight text-foreground leading-[1.1]"
|
||||
>
|
||||
Hubungkan Impianmu <br />
|
||||
<span className="text-transparent bg-clip-text bg-gradient-to-r from-primary via-primary/80 to-primary/40 italic">
|
||||
Ke Negeri Sakura
|
||||
</span>
|
||||
</motion.h1>
|
||||
|
||||
<motion.p
|
||||
variants={itemVariants}
|
||||
className="max-w-2xl text-lg md:text-xl text-muted-foreground leading-relaxed font-medium"
|
||||
>
|
||||
Platform edukasi terdepan untuk penguasaan Bahasa Jepang & karir profesional.
|
||||
Belajar JLPT N5 hingga N2 dengan kurikulum modern dan Spaced Repetition System.
|
||||
</motion.p>
|
||||
|
||||
<motion.div variants={itemVariants} className="flex flex-col sm:flex-row gap-5 mt-4">
|
||||
<Button asChild size="lg" className="rounded-full bg-primary hover:bg-primary/90 text-white min-w-[180px] h-14 shadow-xl shadow-primary/20 font-bold text-lg">
|
||||
<Link href={route('register')}>
|
||||
Mulai Belajar Gratis
|
||||
<ArrowRight className="w-5 h-5 ml-2" />
|
||||
</Link>
|
||||
</Button>
|
||||
<Button asChild size="lg" variant="outline" className="rounded-full border-border hover:bg-muted min-w-[180px] h-14 font-bold text-lg text-foreground">
|
||||
<Link href="#programs">
|
||||
Lihat Program
|
||||
</Link>
|
||||
</Button>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
91
tmp_hero_v1.tsx
Normal file
91
tmp_hero_v1.tsx
Normal file
@@ -0,0 +1,91 @@
|
||||
"use client";
|
||||
|
||||
import { motion, Variants } from "framer-motion";
|
||||
import { ArrowRight, Sparkles } from "lucide-react";
|
||||
import { Button } from "@/Components/ui/button";
|
||||
import { Link } from "@inertiajs/react";
|
||||
|
||||
const containerVariants: Variants = {
|
||||
hidden: { opacity: 0 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
transition: {
|
||||
staggerChildren: 0.2,
|
||||
delayChildren: 0.3,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const itemVariants: Variants = {
|
||||
hidden: { y: 20, opacity: 0 },
|
||||
visible: {
|
||||
y: 0,
|
||||
opacity: 1,
|
||||
transition: {
|
||||
duration: 0.8,
|
||||
ease: [0.215, 0.610, 0.355, 1.000],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export function Hero() {
|
||||
return (
|
||||
<section className="relative min-h-screen flex flex-col items-center justify-center overflow-hidden w-full bg-background selection:bg-primary/30 selection:text-primary pt-20">
|
||||
{/* Background Gradients - Boosted for Light Mode using CSS variables */}
|
||||
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-[1000px] h-[600px] bg-primary/20 dark:bg-primary/10 blur-[120px] rounded-full opacity-[var(--hero-glow-opacity)] pointer-events-none" />
|
||||
<div className="absolute bottom-0 right-0 w-[800px] h-[800px] bg-blue-500/10 dark:bg-blue-500/5 blur-[150px] rounded-full opacity-[var(--hero-glow-opacity)] pointer-events-none" />
|
||||
|
||||
{/* Grid Pattern Overlay */}
|
||||
<div className="absolute inset-0 bg-grid z-0" />
|
||||
|
||||
{/* Japanese Wave Pattern - Adjusted Opacity */}
|
||||
<div className="absolute inset-0 bg-seigaiha z-0 opacity-80 dark:opacity-40" />
|
||||
|
||||
<motion.div
|
||||
variants={containerVariants}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
className="relative z-10 container px-4 mx-auto flex flex-col items-center text-center gap-8"
|
||||
>
|
||||
<motion.div variants={itemVariants}>
|
||||
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full border border-primary/10 bg-primary/5 backdrop-blur-sm shadow-inner text-sm text-primary font-bold mb-6">
|
||||
<Sparkles className="w-4 h-4" />
|
||||
<span>Pendaftaran Batch 2026 Dibuka!</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
<motion.h1
|
||||
variants={itemVariants}
|
||||
className="text-5xl md:text-7xl lg:text-8xl font-black tracking-tight text-foreground leading-[1.1]"
|
||||
>
|
||||
Hubungkan Impianmu <br />
|
||||
<span className="text-transparent bg-clip-text bg-gradient-to-r from-primary via-primary/80 to-primary/40 italic">
|
||||
Ke Negeri Sakura
|
||||
</span>
|
||||
</motion.h1>
|
||||
|
||||
<motion.p
|
||||
variants={itemVariants}
|
||||
className="max-w-2xl text-lg md:text-xl text-muted-foreground leading-relaxed font-medium"
|
||||
>
|
||||
Platform edukasi terdepan untuk penguasaan Bahasa Jepang & karir profesional.
|
||||
Belajar JLPT N5 hingga N2 dengan kurikulum modern dan Spaced Repetition System.
|
||||
</motion.p>
|
||||
|
||||
<motion.div variants={itemVariants} className="flex flex-col sm:flex-row gap-5 mt-4">
|
||||
<Button asChild size="lg" className="rounded-full bg-primary hover:bg-primary/90 text-white min-w-[180px] h-14 shadow-xl shadow-primary/20 font-bold text-lg">
|
||||
<Link href={route('register')}>
|
||||
Mulai Belajar Gratis
|
||||
<ArrowRight className="w-5 h-5 ml-2" />
|
||||
</Link>
|
||||
</Button>
|
||||
<Button asChild size="lg" variant="outline" className="rounded-full border-border hover:bg-muted min-w-[180px] h-14 font-bold text-lg text-foreground">
|
||||
<Link href="#programs">
|
||||
Lihat Program
|
||||
</Link>
|
||||
</Button>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user