Implement all core features: Knowledge pipeline, RAG chat, Todos, Habits, Study Cards, Tags, Dashboard

- Google OAuth authentication with callback flow
- Knowledge ingest pipeline (TEXT/WEB/YOUTUBE → chunking → categorization → embedding)
- OCI GenAI integration (chat, embeddings) with multi-model support
- Semantic search via Oracle VECTOR_DISTANCE
- RAG-based AI chat with source attribution
- Todos with subtasks, filters, and priority levels
- Habits with daily check-in, streak tracking, and color customization
- Study Cards with SM-2 spaced repetition and LLM auto-generation
- Tags system with knowledge item mapping
- Dashboard with live data from all modules

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-30 21:43:51 +00:00
parent 3d2aa6cf46
commit 9929322de0
41 changed files with 11435 additions and 156 deletions

View File

@@ -1,25 +1,32 @@
"use client";
import { useState } from "react";
import { useEffect } from "react";
import { useRouter } from "next/navigation";
import { useAuth } from "@/lib/auth-context";
const GOOGLE_CLIENT_ID = process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID || "";
const REDIRECT_URI = `${typeof window !== "undefined" ? window.location.origin : ""}/login/callback`;
export default function LoginPage() {
const router = useRouter();
const { login } = useAuth();
const [isLoading, setIsLoading] = useState(false);
const { isAuthenticated, isLoading } = useAuth();
const handleGoogleLogin = async () => {
setIsLoading(true);
try {
// TODO: Implement Google OAuth flow
// For now, placeholder
alert("Google OAuth not configured yet");
} catch (error) {
console.error("Login failed:", error);
} finally {
setIsLoading(false);
useEffect(() => {
if (!isLoading && isAuthenticated) {
router.replace("/dashboard");
}
}, [isAuthenticated, isLoading, router]);
const handleGoogleLogin = () => {
const params = new URLSearchParams({
client_id: GOOGLE_CLIENT_ID,
redirect_uri: REDIRECT_URI,
response_type: "code",
scope: "openid email profile",
access_type: "offline",
prompt: "consent",
});
window.location.href = `https://accounts.google.com/o/oauth2/v2/auth?${params.toString()}`;
};
return (
@@ -33,8 +40,7 @@ export default function LoginPage() {
</div>
<button
onClick={handleGoogleLogin}
disabled={isLoading}
className="w-full py-3 px-4 bg-white text-gray-800 rounded-lg font-medium hover:bg-gray-100 transition-colors disabled:opacity-50 flex items-center justify-center gap-3"
className="w-full py-3 px-4 bg-white text-gray-800 rounded-lg font-medium hover:bg-gray-100 transition-colors flex items-center justify-center gap-3"
>
<svg className="w-5 h-5" viewBox="0 0 24 24">
<path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z"/>
@@ -42,7 +48,7 @@ export default function LoginPage() {
<path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/>
<path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/>
</svg>
{isLoading ? "Signing in..." : "Sign in with Google"}
Sign in with Google
</button>
</div>
</div>