Add UI/logical temporal ordering feature
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import type { DragEvent } from 'react';
|
||||
import { useGetStickies, useClusterStickies } from '../api/api';
|
||||
import type { Sticky as StickyType } from '../types/types';
|
||||
import type { Sticky as StickyType, RankedCluster } from '../types/types';
|
||||
import Sticky from './sticky';
|
||||
import Button from './button';
|
||||
import '../styles/stickies.css';
|
||||
@@ -14,10 +16,22 @@ const scoreLabel = (score: number): string => {
|
||||
const Stickies = () => {
|
||||
const { data: stickies, isLoading, error } = useGetStickies();
|
||||
const { mutate: cluster, data: clusterResponse, isPending } = useClusterStickies();
|
||||
|
||||
const [rankedClusters, setRankedClusters] = useState<RankedCluster[]>([]);
|
||||
const dragIndex = useRef<number | null>(null);
|
||||
const [dragOverIndex, setDragOverIndex] = useState<number | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (clusterResponse?.clusters) {
|
||||
setRankedClusters(
|
||||
clusterResponse.clusters.map((c, i) => ({ ...c, rank: i + 1 }))
|
||||
);
|
||||
}
|
||||
}, [clusterResponse]);
|
||||
|
||||
if (isLoading) return <div>Loading...</div>;
|
||||
if (error) return <div>Error: {error.message}</div>;
|
||||
|
||||
const clusters = clusterResponse?.clusters;
|
||||
const score = clusterResponse?.score;
|
||||
|
||||
const handleCluster = () => {
|
||||
@@ -35,19 +49,69 @@ const Stickies = () => {
|
||||
const renderStickies = (items: StickyType[]) =>
|
||||
items?.map((sticky) => <Sticky key={sticky.id} sticky={sticky} />);
|
||||
|
||||
const handleDragStart = (index: number) => {
|
||||
dragIndex.current = index;
|
||||
};
|
||||
|
||||
const handleDragOver = (e: DragEvent, index: number) => {
|
||||
e.preventDefault();
|
||||
setDragOverIndex(index);
|
||||
};
|
||||
|
||||
const handleDragLeave = () => {
|
||||
setDragOverIndex(null);
|
||||
};
|
||||
|
||||
const handleDrop = (targetIndex: number) => {
|
||||
const sourceIndex = dragIndex.current;
|
||||
if (sourceIndex === null || sourceIndex === targetIndex) {
|
||||
dragIndex.current = null;
|
||||
setDragOverIndex(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const reordered = [...rankedClusters];
|
||||
const [moved] = reordered.splice(sourceIndex, 1);
|
||||
reordered.splice(targetIndex, 0, moved);
|
||||
|
||||
setRankedClusters(reordered.map((c, i) => ({ ...c, rank: i + 1 })));
|
||||
dragIndex.current = null;
|
||||
setDragOverIndex(null);
|
||||
};
|
||||
|
||||
const handleDragEnd = () => {
|
||||
dragIndex.current = null;
|
||||
setDragOverIndex(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="stickies-container">
|
||||
<Button onClick={handleCluster} isLoading={isPending} label="Group Stickies By Topic" />
|
||||
{clusters ? (
|
||||
{rankedClusters.length > 0 ? (
|
||||
<div className="clusters-container">
|
||||
{score != null && (
|
||||
<div className="cohesion-score">
|
||||
Cluster cohesion: <strong>{score.toFixed(2)}</strong> — {scoreLabel(score)}
|
||||
</div>
|
||||
)}
|
||||
{clusters.map((group) => (
|
||||
<div key={group.label} className="cluster-group">
|
||||
<h3 className="cluster-label">{group.label}</h3>
|
||||
{rankedClusters.map((group, index) => (
|
||||
<div
|
||||
key={group.label}
|
||||
className={`cluster-group cluster-draggable${dragOverIndex === index ? ' cluster-drag-over' : ''}`}
|
||||
draggable
|
||||
onDragStart={() => handleDragStart(index)}
|
||||
onDragOver={(e) => handleDragOver(e, index)}
|
||||
onDragLeave={handleDragLeave}
|
||||
onDrop={() => handleDrop(index)}
|
||||
onDragEnd={handleDragEnd}
|
||||
>
|
||||
<div className="cluster-header">
|
||||
<span className="cluster-rank" aria-label={`Priority ${group.rank}`}>
|
||||
{group.rank}
|
||||
</span>
|
||||
<h3 className="cluster-label">{group.label}</h3>
|
||||
<span className="cluster-drag-handle" aria-hidden="true">⠿</span>
|
||||
</div>
|
||||
<div className="stickies-grid">
|
||||
{renderStickies(
|
||||
group?.noteIds
|
||||
|
||||
Reference in New Issue
Block a user