linguabot commited on
Commit
303d65d
·
verified ·
1 Parent(s): 611cdf0

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. client/src/components/Refinity.tsx +57 -29
client/src/components/Refinity.tsx CHANGED
@@ -1,4 +1,5 @@
1
  import React from 'react';
 
2
  import { api } from '../services/api';
3
 
4
  type Stage = 'task' | 'flow' | 'preview' | 'editor';
@@ -350,13 +351,13 @@ const Refinity: React.FC = () => {
350
  </div>
351
  )}
352
 
353
- {/* Stage 2: Version Flow */}
354
  {stage === 'flow' && (
355
  <div>
356
  <div className="flex items-center justify-between mb-4">
357
  <div>
358
  <h3 className="text-xl font-semibold text-black">Version Flow — {task?.title}</h3>
359
- <div className="text-gray-700 text-sm">Scroll to browse. Center card is focused.</div>
360
  </div>
361
  <div className="flex gap-2">
362
  <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,34 +368,61 @@ const Refinity: React.FC = () => {
367
  </div>
368
  </div>
369
 
370
- <div className="relative py-4">
371
- <div className="absolute left-2 top-1/2 -translate-y-1/2 z-10">
372
- <button onClick={()=> setFlowIndex((i)=> Math.max(i-1, 0))} className="px-2 py-1 rounded-2xl bg-white/50 ring-1 ring-white/50 backdrop-blur-md text-sm"></button>
373
- </div>
374
- <div className="absolute right-2 top-1/2 -translate-y-1/2 z-10">
375
- <button onClick={()=> setFlowIndex((i)=> Math.min(i+1, Math.max(taskVersions.length-1, 0)))} className="px-2 py-1 rounded-2xl bg-white/50 ring-1 ring-white/50 backdrop-blur-md text-sm">›</button>
376
- </div>
377
- <div className="overflow-x-auto px-16">
378
- <div className="inline-flex gap-6 pb-2">
379
- {taskVersions.map((v, idx) => {
380
- const snippet = (v.content || '').slice(0, 200) + ((v.content || '').length > 200 ? '…' : '');
381
- return (
382
- <div key={v.id} className="snap-center flex-shrink-0 w-[560px]">
383
- <div className="relative rounded-xl p-5 bg-white/10 backdrop-blur-md ring-1 ring-inset ring-white/30 shadow-[0_20px_40px_rgba(0,0,0,0.08),inset_0_0.5px_0_rgba(255,255,255,0.5),inset_0_-1px_1.5px_rgba(0,0,0,0.12)] text-base">
384
- <div className="text-gray-800 text-sm mb-2">Original: {v.originalAuthor}</div>
385
- <div className="text-gray-600 text-xs mb-3">Revised by: {v.revisedBy ? `${v.revisedBy} (v${v.versionNumber})` : `— (v${v.versionNumber})`}</div>
386
- <div className="text-gray-900 whitespace-pre-wrap break-words leading-relaxed">{snippet}</div>
387
- <div className="mt-4 flex gap-3">
388
- <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>
389
- <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>
390
- <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>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
391
  </div>
392
- </div>
393
- </div>
394
- );
395
- })}
396
- </div>
397
- </div>
398
  </div>
399
  </div>
400
  )}
 
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';
 
351
  </div>
352
  )}
353
 
354
+ {/* Stage 2: Version Flow - Framer Motion 3-card deck */}
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">Use arrows or click cards. Center card is active.</div>
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">
 
368
  </div>
369
  </div>
370
 
371
+ <div className="relative h-[420px]">
372
+ <button aria-label="Previous" onClick={()=> setFlowIndex(i => Math.max(i-1, 0))} className="absolute left-2 top-1/2 -translate-y-1/2 z-10 px-2 py-1 rounded-2xl bg-white/50 ring-1 ring-white/50 backdrop-blur-md text-sm">‹</button>
373
+ <button aria-label="Next" onClick={()=> setFlowIndex(i => Math.min(i+1, Math.max(taskVersions.length-1, 0)))} className="absolute right-2 top-1/2 -translate-y-1/2 z-10 px-2 py-1 rounded-2xl bg-white/50 ring-1 ring-white/50 backdrop-blur-md text-sm"></button>
374
+
375
+ {(() => {
376
+ const n = taskVersions.length;
377
+ if (n === 0) return (
378
+ <div className="h-full grid place-items-center text-gray-600">No versions yet.</div>
379
+ );
380
+ const center = Math.min(Math.max(flowIndex, 0), n - 1);
381
+ const ids: Array<{ pos: 'left'|'center'|'right'; idx: number }> = [];
382
+ if (center - 1 >= 0) ids.push({ pos: 'left', idx: center - 1 });
383
+ ids.push({ pos: 'center', idx: center });
384
+ if (center + 1 < n) ids.push({ pos: 'right', idx: center + 1 });
385
+
386
+ const variants = {
387
+ left: { x: '-32%', scale: 0.98, rotate: -2, opacity: 0.95, zIndex: 10 },
388
+ center: { x: '-50%', scale: 1.0, rotate: 0, opacity: 1, zIndex: 20 },
389
+ right: { x: '-68%', scale: 0.98, rotate: 2, opacity: 0.95, zIndex: 10 }
390
+ } as const;
391
+
392
+ return (
393
+ <AnimatePresence initial={false}>
394
+ {ids.map(({ pos, idx }) => {
395
+ const v = taskVersions[idx];
396
+ const snippet = (v.content || '').slice(0, 220) + ((v.content || '').length > 220 ? '…' : '');
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/10 backdrop-blur-md ring-1 ring-inset ring-white/30 shadow-[0_20px_40px_rgba(0,0,0,0.08),inset_0_0.5px_0_rgba(255,255,255,0.5),inset_0_-1px_1.5px_rgba(0,0,0,0.12)] 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
+ </motion.div>
421
+ );
422
+ })}
423
+ </AnimatePresence>
424
+ );
425
+ })()}
426
  </div>
427
  </div>
428
  )}