Upload folder using huggingface_hub
Browse files
client/src/components/Refinity.tsx
CHANGED
|
@@ -1,5 +1,10 @@
|
|
| 1 |
import React from 'react';
|
| 2 |
import { motion, AnimatePresence } from 'framer-motion';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
import { api } from '../services/api';
|
| 4 |
|
| 5 |
type Stage = 'task' | 'flow' | 'preview' | 'editor';
|
|
@@ -233,15 +238,8 @@ const Refinity: React.FC = () => {
|
|
| 233 |
|
| 234 |
return (
|
| 235 |
<div className="relative">
|
| 236 |
-
{/*
|
| 237 |
-
<div className="
|
| 238 |
-
{/* Glass card container */}
|
| 239 |
-
<div className="relative rounded-xl bg-white/10 backdrop-blur-md ring-1 ring-inset ring-white/30 shadow-[inset_0_0.5px_0_rgba(255,255,255,0.5),inset_0_-1px_1.5px_rgba(0,0,0,0.12)]">
|
| 240 |
-
<div className="pointer-events-none absolute inset-0 rounded-xl opacity-50 [background:linear-gradient(to_bottom,rgba(255,255,255,0.3),rgba(255,255,255,0)_28%),linear-gradient(to_right,rgba(255,255,255,0.28),rgba(255,255,255,0)_28%)]" />
|
| 241 |
-
<div className="pointer-events-none absolute inset-0 rounded-xl bg-gradient-to-tr from-white/30 via-white/10 to-transparent opacity-45" />
|
| 242 |
-
<div className="pointer-events-none absolute inset-0 rounded-xl" style={{ background: 'radial-gradient(120% 120% at 50% 55%, rgba(0,0,0,0.03), rgba(0,0,0,0) 60%)' }} />
|
| 243 |
-
<div className="pointer-events-none absolute inset-0 rounded-xl bg-indigo-500/10 mix-blend-overlay opacity-30" />
|
| 244 |
-
<div className="relative p-6">
|
| 245 |
{/* Stage 1: Task Creation / Selection */}
|
| 246 |
{stage === 'task' && (
|
| 247 |
<div>
|
|
@@ -351,13 +349,13 @@ const Refinity: React.FC = () => {
|
|
| 351 |
</div>
|
| 352 |
)}
|
| 353 |
|
| 354 |
-
{/* Stage 2: Version Flow -
|
| 355 |
{stage === 'flow' && (
|
| 356 |
<div>
|
| 357 |
<div className="flex items-center justify-between mb-4">
|
| 358 |
<div>
|
| 359 |
<h3 className="text-xl font-semibold text-black">Version Flow — {task?.title}</h3>
|
| 360 |
-
<div className="text-gray-700 text-sm">
|
| 361 |
</div>
|
| 362 |
<div className="flex gap-2">
|
| 363 |
<button onClick={()=>setStage('task')} className="relative overflow-hidden inline-flex items-center justify-center gap-2 px-3 py-2 text-sm font-medium rounded-2xl text-black ring-1 ring-inset ring-white/50 backdrop-blur-md bg-white/30 active:translate-y-0.5 transition-all duration-200">
|
|
@@ -367,62 +365,40 @@ const Refinity: React.FC = () => {
|
|
| 367 |
</button>
|
| 368 |
</div>
|
| 369 |
</div>
|
| 370 |
-
|
| 371 |
-
|
| 372 |
-
|
| 373 |
-
|
| 374 |
-
|
| 375 |
-
|
| 376 |
-
|
| 377 |
-
|
| 378 |
-
|
| 379 |
-
|
| 380 |
-
|
| 381 |
-
|
| 382 |
-
|
| 383 |
-
|
| 384 |
-
|
| 385 |
-
|
| 386 |
-
|
| 387 |
-
|
| 388 |
-
|
| 389 |
-
|
| 390 |
-
|
| 391 |
-
|
| 392 |
-
|
| 393 |
-
|
| 394 |
-
|
| 395 |
-
|
| 396 |
-
|
| 397 |
-
const isCenter = pos === 'center';
|
| 398 |
-
return (
|
| 399 |
-
<motion.div
|
| 400 |
-
key={v.id}
|
| 401 |
-
className="absolute top-0 left-1/2 w-[560px]"
|
| 402 |
-
initial={variants[pos]}
|
| 403 |
-
animate={variants[pos]}
|
| 404 |
-
exit={variants[pos]}
|
| 405 |
-
transition={{ type: 'spring', stiffness: 300, damping: 28 }}
|
| 406 |
-
onClick={() => { if (!isCenter) setFlowIndex(idx); }}
|
| 407 |
-
>
|
| 408 |
-
<div className="relative rounded-xl p-5 bg-white ring-1 ring-gray-200 shadow-lg text-base">
|
| 409 |
-
<div className="text-gray-800 text-sm mb-2">Original: {v.originalAuthor}</div>
|
| 410 |
-
<div className="text-gray-600 text-xs mb-3">Revised by: {v.revisedBy ? `${v.revisedBy} (v${v.versionNumber})` : `— (v${v.versionNumber})`}</div>
|
| 411 |
-
<div className="text-gray-900 whitespace-pre-wrap break-words leading-relaxed">{snippet}</div>
|
| 412 |
-
{isCenter && (
|
| 413 |
-
<div className="mt-4 flex gap-3">
|
| 414 |
-
<button onClick={()=>{ setPreviewVersionId(v.id); setStage('preview'); }} className="relative overflow-hidden inline-flex items-center justify-center gap-2 px-3 py-2 text-sm font-medium rounded-2xl text-black ring-1 ring-inset ring-white/50 backdrop-blur-md bg-white/30 active:translate-y-0.5 transition-all duration-200">Full Text</button>
|
| 415 |
-
<button onClick={()=>selectManual(v.id)} className="relative overflow-hidden inline-flex items-center justify-center gap-2 px-3 py-2 text-sm font-medium rounded-2xl text-white ring-1 ring-inset ring-white/50 backdrop-blur-md backdrop-brightness-110 backdrop-saturate-150 bg-indigo-600/70 active:translate-y-0.5 transition-all duration-200">Revise</button>
|
| 416 |
-
<button onClick={()=>{ setPreviewVersionId(v.id); setShowPreviewDiff(true); setStage('preview'); }} className="relative overflow-hidden inline-flex items-center justify-center gap-2 px-3 py-2 text-sm font-medium rounded-2xl text-black ring-1 ring-inset ring-white/50 backdrop-blur-md bg-white/30 active:translate-y-0.5 transition-all duration-200">Compare</button>
|
| 417 |
-
</div>
|
| 418 |
-
)}
|
| 419 |
</div>
|
| 420 |
-
|
| 421 |
-
|
| 422 |
-
|
| 423 |
-
|
| 424 |
-
)
|
| 425 |
-
|
| 426 |
</div>
|
| 427 |
</div>
|
| 428 |
)}
|
|
@@ -449,7 +425,6 @@ const Refinity: React.FC = () => {
|
|
| 449 |
nextVersionNumber={((versions.filter(v=>v.taskId===(task?.id||'')).slice(-1)[0]?.versionNumber) || 0) + 1}
|
| 450 |
/>
|
| 451 |
)}
|
| 452 |
-
</div>
|
| 453 |
</div>
|
| 454 |
</div>
|
| 455 |
);
|
|
|
|
| 1 |
import React from 'react';
|
| 2 |
import { motion, AnimatePresence } from 'framer-motion';
|
| 3 |
+
import { Swiper as SwiperRoot, SwiperSlide } from 'swiper/react';
|
| 4 |
+
import { EffectCoverflow, Navigation, A11y } from 'swiper/modules';
|
| 5 |
+
import 'swiper/css';
|
| 6 |
+
import 'swiper/css/effect-coverflow';
|
| 7 |
+
import 'swiper/css/navigation';
|
| 8 |
import { api } from '../services/api';
|
| 9 |
|
| 10 |
type Stage = 'task' | 'flow' | 'preview' | 'editor';
|
|
|
|
| 238 |
|
| 239 |
return (
|
| 240 |
<div className="relative">
|
| 241 |
+
{/* Clean container (no purple gradient) */}
|
| 242 |
+
<div className="relative rounded-xl p-6 bg-transparent">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 243 |
{/* Stage 1: Task Creation / Selection */}
|
| 244 |
{stage === 'task' && (
|
| 245 |
<div>
|
|
|
|
| 349 |
</div>
|
| 350 |
)}
|
| 351 |
|
| 352 |
+
{/* Stage 2: Version Flow - Swiper Coverflow */}
|
| 353 |
{stage === 'flow' && (
|
| 354 |
<div>
|
| 355 |
<div className="flex items-center justify-between mb-4">
|
| 356 |
<div>
|
| 357 |
<h3 className="text-xl font-semibold text-black">Version Flow — {task?.title}</h3>
|
| 358 |
+
<div className="text-gray-700 text-sm">Swipe/click to browse. Center slide is active.</div>
|
| 359 |
</div>
|
| 360 |
<div className="flex gap-2">
|
| 361 |
<button onClick={()=>setStage('task')} className="relative overflow-hidden inline-flex items-center justify-center gap-2 px-3 py-2 text-sm font-medium rounded-2xl text-black ring-1 ring-inset ring-white/50 backdrop-blur-md bg-white/30 active:translate-y-0.5 transition-all duration-200">
|
|
|
|
| 365 |
</button>
|
| 366 |
</div>
|
| 367 |
</div>
|
| 368 |
+
<div className="relative">
|
| 369 |
+
<SwiperRoot
|
| 370 |
+
modules={[EffectCoverflow, Navigation, A11y]}
|
| 371 |
+
effect="coverflow"
|
| 372 |
+
onSlideChange={(s)=> setFlowIndex(s.activeIndex)}
|
| 373 |
+
onAfterInit={(s)=> setFlowIndex(s.activeIndex)}
|
| 374 |
+
navigation
|
| 375 |
+
centeredSlides
|
| 376 |
+
slidesPerView={1.2}
|
| 377 |
+
spaceBetween={24}
|
| 378 |
+
coverflowEffect={{ rotate: 0, stretch: 40, depth: 80, modifier: 1, slideShadows: false }}
|
| 379 |
+
className="!px-8"
|
| 380 |
+
>
|
| 381 |
+
{taskVersions.map((v, idx) => {
|
| 382 |
+
const snippet = (v.content || '').slice(0, 220) + ((v.content || '').length > 220 ? '…' : '');
|
| 383 |
+
const isCenter = idx === flowIndex;
|
| 384 |
+
return (
|
| 385 |
+
<SwiperSlide key={v.id} style={{ width: 560 }}>
|
| 386 |
+
<div className="relative rounded-xl p-5 bg-white ring-1 ring-gray-200 shadow-lg text-base">
|
| 387 |
+
<div className="text-gray-800 text-sm mb-2">Original: {v.originalAuthor}</div>
|
| 388 |
+
<div className="text-gray-600 text-xs mb-3">Revised by: {v.revisedBy ? `${v.revisedBy} (v${v.versionNumber})` : `— (v${v.versionNumber})`}</div>
|
| 389 |
+
<div className="text-gray-900 whitespace-pre-wrap break-words leading-relaxed">{snippet}</div>
|
| 390 |
+
{isCenter && (
|
| 391 |
+
<div className="mt-4 flex gap-3">
|
| 392 |
+
<button onClick={()=>{ setPreviewVersionId(v.id); setStage('preview'); }} className="relative overflow-hidden inline-flex items-center justify-center gap-2 px-3 py-2 text-sm font-medium rounded-2xl text-black ring-1 ring-inset ring-white/50 backdrop-blur-md bg-white/30 active:translate-y-0.5 transition-all duration-200">Full Text</button>
|
| 393 |
+
<button onClick={()=>selectManual(v.id)} className="relative overflow-hidden inline-flex items-center justify-center gap-2 px-3 py-2 text-sm font-medium rounded-2xl text-white ring-1 ring-inset ring-white/50 backdrop-blur-md backdrop-brightness-110 backdrop-saturate-150 bg-indigo-600/70 active:translate-y-0.5 transition-all duration-200">Revise</button>
|
| 394 |
+
<button onClick={()=>{ setPreviewVersionId(v.id); setShowPreviewDiff(true); setStage('preview'); }} className="relative overflow-hidden inline-flex items-center justify-center gap-2 px-3 py-2 text-sm font-medium rounded-2xl text-black ring-1 ring-inset ring-white/50 backdrop-blur-md bg-white/30 active:translate-y-0.5 transition-all duration-200">Compare</button>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 395 |
</div>
|
| 396 |
+
)}
|
| 397 |
+
</div>
|
| 398 |
+
</SwiperSlide>
|
| 399 |
+
);
|
| 400 |
+
})}
|
| 401 |
+
</SwiperRoot>
|
| 402 |
</div>
|
| 403 |
</div>
|
| 404 |
)}
|
|
|
|
| 425 |
nextVersionNumber={((versions.filter(v=>v.taskId===(task?.id||'')).slice(-1)[0]?.versionNumber) || 0) + 1}
|
| 426 |
/>
|
| 427 |
)}
|
|
|
|
| 428 |
</div>
|
| 429 |
</div>
|
| 430 |
);
|