Files
Momento/architectural-grid10/src/components/SettingsView.tsx
Antigravity 03e6a62b80
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m12s
feat: migrate semantic search to pgvector + full-text search
Replace JSON-string embeddings with native pgvector(1536) storage and
add PostgreSQL full-text search (tsvector/GIN) with Reciprocal Rank Fusion
for hybrid keyword + semantic ranking.

Changes:
- NoteEmbedding.embedding: String → vector(1536) via pgvector
- NoteEmbedding: added updatedAt for reindex tracking
- Note: added tsv (tsvector) with auto-update trigger for FTS
- semantic-search.service: hybrid FTS + vector search with RRF fusion
- embedding.service: toVectorString() for pgvector SQL literals
- Removed JS-side cosine similarity loops (now DB-side via <=>)
- Added HNSW index on NoteEmbedding.embedding (cosine distance)
- Added GIN index on Note.tsv for FTS queries

Schema migration in: prisma/migrations/20260512120000_pgvector_and_fts_search/

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 07:03:56 +00:00

67 lines
2.7 KiB
TypeScript

import React from 'react';
import { motion, AnimatePresence } from 'motion/react';
import { SettingsTab } from '../types';
import { SettingsHeader } from './settings/SettingsHeader';
import { GeneralTab } from './settings/GeneralTab';
import { AITab } from './settings/AITab';
import { AppearanceTab } from './settings/AppearanceTab';
interface SettingsViewProps {
activeSettingsTab: SettingsTab;
setActiveSettingsTab: (tab: SettingsTab) => void;
}
export const SettingsView: React.FC<SettingsViewProps> = ({
activeSettingsTab,
setActiveSettingsTab
}) => {
return (
<div className="h-full flex flex-col bg-paper dark:bg-dark-paper overflow-y-auto custom-scrollbar relative font-sans">
<div className="absolute inset-0 opacity-[0.04] pointer-events-none grainy-bg mix-blend-multiply dark:mix-blend-overlay" />
<div className="relative z-10 flex flex-col min-h-full">
<SettingsHeader
activeTab={activeSettingsTab}
setActiveTab={setActiveSettingsTab}
/>
<div className="flex-1 px-12 pb-24 h-full">
<div className="max-w-6xl mx-auto">
<AnimatePresence mode="wait">
{activeSettingsTab === 'general' && (
<GeneralTab key="general" />
)}
{activeSettingsTab === 'ai' && (
<AITab key="ai" />
)}
{activeSettingsTab === 'appearance' && (
<AppearanceTab key="appearance" />
)}
{['profile', 'data', 'mcp', 'about'].includes(activeSettingsTab) && (
<motion.div
key="placeholder"
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
className="h-[50vh] flex flex-col items-center justify-center border border-dashed border-border rounded-[32px] space-y-6 bg-white/20 dark:bg-white/5"
>
<div className="w-16 h-16 rounded-3xl border border-dashed border-concrete/20 flex items-center justify-center text-concrete/40 bg-paper/50">
<span className="text-2xl font-serif italic text-concrete">?</span>
</div>
<div className="text-center space-y-1">
<p className="text-ink font-bold text-sm tracking-tight">Section en développement</p>
<p className="text-concrete italic text-[11px] font-light">Le module {activeSettingsTab} sera disponible prochainement.</p>
</div>
</motion.div>
)}
</AnimatePresence>
</div>
</div>
</div>
</div>
);
};