feat: add form components and UI elements for enhanced user interaction
- Introduced Form, FormField, FormItem, FormLabel, FormControl, FormDescription, FormMessage components for structured form handling. - Added Input, Textarea, and Select components for user input. - Implemented Label and Separator components for better UI organization. - Created Skeleton component for loading states. - Developed Toast and Toaster components for user notifications. - Integrated useToast hook for managing toast notifications. - Established AI analysis functionality with analyzeJournalWithLocalAI. - Set up Dexie for local database management with Journal and Task models. - Configured Supabase client for server-side and browser-side interactions. - Defined database schema for journals, tasks, chat sessions, and messages with Row Level Security policies. Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
co-authored by
Copilot
parent
3432bbab33
commit
c73bf0e499
@@ -0,0 +1,48 @@
|
||||
export interface AIAnalysisResult {
|
||||
ai_tags: string[];
|
||||
ai_sentiment_score: number;
|
||||
ai_summary: string;
|
||||
suggested_tasks: string[];
|
||||
}
|
||||
|
||||
export async function analyzeJournalWithLocalAI(content: string, model: string = "llama3"): Promise<AIAnalysisResult | null> {
|
||||
const prompt = `
|
||||
Sen şefkatli bir yapay zeka asistanı ve kişisel yansıma (reflection) yardımcısısın.
|
||||
Aşağıdaki günlük girdisini analiz edip tam olarak belirtilen JSON formatında yanıt vermelisin. Düz metin kullanma, SADECE geçerli bir JSON objesi döndür.
|
||||
|
||||
Günlük Metni: "${content}"
|
||||
|
||||
İstenen JSON Formatı:
|
||||
{
|
||||
"ai_tags": ["#duygu", "#konu", vb.],
|
||||
"ai_sentiment_score": 0.5, // -1.0 (çok negatif) ile +1.0 (çok pozitif) arası ondalıklı bir değer
|
||||
"ai_summary": "Kullanıcının durumunu özetleyen 1-2 cümlelik şefkatli geri bildirim.",
|
||||
"suggested_tasks": ["yapılabilecek pratik aksiyon 1", "aksiyon 2"] // Eylem gerektirmiyorsa boş dizi []
|
||||
}
|
||||
`;
|
||||
|
||||
try {
|
||||
const response = await fetch("http://localhost:11434/api/generate", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
model: model, // Gerekirse "gemini-3-flash-preview:latest" gibi kendi modeliniz de olabilir
|
||||
prompt: prompt,
|
||||
stream: false,
|
||||
format: "json"
|
||||
})
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Ollama API Hatası: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
const parsedResult = JSON.parse(data.response);
|
||||
return parsedResult as AIAnalysisResult;
|
||||
|
||||
} catch (error) {
|
||||
console.error("AI Analizi başarısız oldu (Ollama açık olmayabilir):", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import Dexie, { type Table } from "dexie";
|
||||
|
||||
// Veritabanı Modelleri
|
||||
export interface Journal {
|
||||
id: string;
|
||||
date: string;
|
||||
mood: string;
|
||||
energy: number;
|
||||
content: string;
|
||||
ai_tags?: string[];
|
||||
ai_sentiment_score?: number;
|
||||
ai_summary?: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export interface Task {
|
||||
id: string;
|
||||
journal_id?: string;
|
||||
title: string;
|
||||
status: "todo" | "in_progress" | "completed";
|
||||
ai_generated: boolean;
|
||||
date: string;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export class MindSpaceDB extends Dexie {
|
||||
journals!: Table<Journal>;
|
||||
tasks!: Table<Task>;
|
||||
|
||||
constructor() {
|
||||
super("MindSpaceDatabase");
|
||||
|
||||
// Schema tanımlamaları.
|
||||
// IndexedDB'de sadece indekslenecek (üzerinde arama/sıralama yapılacak) alanları belirtiriz.
|
||||
this.version(1).stores({
|
||||
journals: "id, date, mood",
|
||||
tasks: "id, status, date, journal_id"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const db = new MindSpaceDB();
|
||||
@@ -0,0 +1,8 @@
|
||||
import { createBrowserClient } from '@supabase/ssr'
|
||||
|
||||
export function createClient() {
|
||||
return createBrowserClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import { createServerClient } from '@supabase/ssr'
|
||||
import { NextResponse, type NextRequest } from 'next/server'
|
||||
|
||||
export async function updateSession(request: NextRequest) {
|
||||
let supabaseResponse = NextResponse.next({
|
||||
request,
|
||||
})
|
||||
|
||||
const supabase = createServerClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
||||
{
|
||||
cookies: {
|
||||
getAll() {
|
||||
return request.cookies.getAll()
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
cookiesToSet.forEach(({ name, value, options }) => request.cookies.set(name, value))
|
||||
supabaseResponse = NextResponse.next({
|
||||
request,
|
||||
})
|
||||
cookiesToSet.forEach(({ name, value, options }) =>
|
||||
supabaseResponse.cookies.set(name, value, options)
|
||||
)
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// IMPORTANT: Avoid writing any logic between createServerClient and
|
||||
// supabase.auth.getUser(). A simple mistake could make it very hard to debug
|
||||
// issues with users being randomly logged out.
|
||||
|
||||
const {
|
||||
data: { user },
|
||||
} = await supabase.auth.getUser()
|
||||
|
||||
if (
|
||||
!user &&
|
||||
!request.nextUrl.pathname.startsWith('/login') &&
|
||||
!request.nextUrl.pathname.startsWith('/auth')
|
||||
) {
|
||||
// no user, potentially respond by redirecting the user to the login page
|
||||
const url = request.nextUrl.clone()
|
||||
url.pathname = '/login'
|
||||
return NextResponse.redirect(url)
|
||||
}
|
||||
|
||||
return supabaseResponse
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { createServerClient } from '@supabase/ssr'
|
||||
import { cookies } from 'next/headers'
|
||||
|
||||
export async function createClient() {
|
||||
const cookieStore = await cookies()
|
||||
|
||||
return createServerClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
||||
{
|
||||
cookies: {
|
||||
getAll() {
|
||||
return cookieStore.getAll()
|
||||
},
|
||||
setAll(cookiesToSet) {
|
||||
try {
|
||||
cookiesToSet.forEach(({ name, value, options }) => {
|
||||
cookieStore.set(name, value, options)
|
||||
})
|
||||
} catch (error) {
|
||||
// The `set` method was called from a Server Component.
|
||||
// This can be ignored if you have middleware refreshing
|
||||
// user sessions.
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { clsx, type ClassValue } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
Reference in New Issue
Block a user