feat: remove recent conversions functionality from units
- Delete ConversionHistory component - Remove history-related logic and state from MainConverter - Clean up history imports and types in CommandPalette and storage utilities - Remove history storage functions from lib/units/storage.ts
This commit is contained in:
@@ -1,122 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { History, Trash2, ArrowRight } from 'lucide-react';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/Card';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import {
|
||||
getHistory,
|
||||
clearHistory,
|
||||
type ConversionRecord,
|
||||
} from '@/lib/units/storage';
|
||||
import { getRelativeTime, formatNumber } from '@/lib/utils';
|
||||
import { formatMeasureName } from '@/lib/units/units';
|
||||
|
||||
interface ConversionHistoryProps {
|
||||
onSelectConversion?: (record: ConversionRecord) => void;
|
||||
}
|
||||
|
||||
export default function ConversionHistory({
|
||||
onSelectConversion,
|
||||
}: ConversionHistoryProps) {
|
||||
const [history, setHistory] = useState<ConversionRecord[]>([]);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
loadHistory();
|
||||
|
||||
// Listen for storage changes
|
||||
const handleStorageChange = () => {
|
||||
loadHistory();
|
||||
};
|
||||
|
||||
window.addEventListener('storage', handleStorageChange);
|
||||
// Also listen for custom event from same window
|
||||
window.addEventListener('historyUpdated', handleStorageChange);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('storage', handleStorageChange);
|
||||
window.removeEventListener('historyUpdated', handleStorageChange);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const loadHistory = () => {
|
||||
setHistory(getHistory());
|
||||
};
|
||||
|
||||
const handleClearHistory = () => {
|
||||
if (confirm('Clear all conversion history?')) {
|
||||
clearHistory();
|
||||
loadHistory();
|
||||
}
|
||||
};
|
||||
|
||||
if (history.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<div className="flex items-center justify-between">
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<History className="h-5 w-5" />
|
||||
Recent Conversions
|
||||
</CardTitle>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
>
|
||||
{isOpen ? 'Hide' : `Show (${history.length})`}
|
||||
</Button>
|
||||
{history.length > 0 && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={handleClearHistory}
|
||||
className="h-8 w-8"
|
||||
>
|
||||
<Trash2 className="h-4 w-4" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</CardHeader>
|
||||
|
||||
{isOpen && (
|
||||
<CardContent>
|
||||
<div className="space-y-2">
|
||||
{history.map((record) => (
|
||||
<button
|
||||
key={record.id}
|
||||
onClick={() => onSelectConversion?.(record)}
|
||||
className="w-full p-3 rounded-lg border hover:bg-accent transition-colors text-left"
|
||||
>
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center gap-2 text-sm font-medium">
|
||||
<span className="truncate">
|
||||
{formatNumber(record.from.value)} {record.from.unit}
|
||||
</span>
|
||||
<ArrowRight className="h-3 w-3 flex-shrink-0" />
|
||||
<span className="truncate">
|
||||
{formatNumber(record.to.value)} {record.to.unit}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-xs text-muted-foreground mt-1">
|
||||
<span>{formatMeasureName(record.measure as any)}</span>
|
||||
<span>•</span>
|
||||
<span>{getRelativeTime(record.timestamp)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
)}
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/Card';
|
||||
import { Input } from '@/components/ui/Input';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import SearchUnits from './SearchUnits';
|
||||
import ConversionHistory from './ConversionHistory';
|
||||
import VisualComparison from './VisualComparison';
|
||||
import CommandPalette from '@/components/units/ui/CommandPalette';
|
||||
import {
|
||||
@@ -21,7 +20,7 @@ import {
|
||||
type ConversionResult,
|
||||
} from '@/lib/units/units';
|
||||
import { parseNumberInput, formatNumber, cn } from '@/lib/utils';
|
||||
import { saveToHistory, getFavorites, toggleFavorite } from '@/lib/units/storage';
|
||||
import { getFavorites, toggleFavorite } from '@/lib/units/storage';
|
||||
|
||||
export default function MainConverter() {
|
||||
const [selectedMeasure, setSelectedMeasure] = useState<Measure>('length');
|
||||
@@ -93,39 +92,12 @@ export default function MainConverter() {
|
||||
setFavorites(getFavorites());
|
||||
}, []);
|
||||
|
||||
// Save to history when conversion happens (but not during dragging)
|
||||
useEffect(() => {
|
||||
if (isDragging) return; // Don't save to history while dragging
|
||||
|
||||
const numValue = parseNumberInput(inputValue);
|
||||
if (numValue !== null && selectedUnit && conversions.length > 0) {
|
||||
// Save first conversion to history
|
||||
const firstConversion = conversions.find(c => c.unit !== selectedUnit);
|
||||
if (firstConversion) {
|
||||
saveToHistory({
|
||||
from: { value: numValue, unit: selectedUnit },
|
||||
to: { value: firstConversion.value, unit: firstConversion.unit },
|
||||
measure: selectedMeasure,
|
||||
});
|
||||
// Dispatch custom event for same-window updates
|
||||
window.dispatchEvent(new Event('historyUpdated'));
|
||||
}
|
||||
}
|
||||
}, [inputValue, selectedUnit, conversions, selectedMeasure, isDragging]);
|
||||
|
||||
// Handle search selection
|
||||
const handleSearchSelect = useCallback((unit: string, measure: Measure) => {
|
||||
setSelectedMeasure(measure);
|
||||
setSelectedUnit(unit);
|
||||
}, []);
|
||||
|
||||
// Handle history selection
|
||||
const handleHistorySelect = useCallback((record: any) => {
|
||||
setInputValue(record.from.value.toString());
|
||||
setSelectedMeasure(record.measure);
|
||||
setSelectedUnit(record.from.unit);
|
||||
}, []);
|
||||
|
||||
// Handle value change from draggable bars
|
||||
const handleValueChange = useCallback((value: number, unit: string, dragging: boolean) => {
|
||||
setIsDragging(dragging);
|
||||
@@ -337,9 +309,6 @@ export default function MainConverter() {
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Conversion History */}
|
||||
<ConversionHistory onSelectConversion={handleHistorySelect} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { Command, Hash, Clock, Star, Moon, Sun } from 'lucide-react';
|
||||
import { Command, Hash, Star, Moon, Sun } from 'lucide-react';
|
||||
import { useTheme } from '@/components/providers/ThemeProvider';
|
||||
import {
|
||||
getAllMeasures,
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
getCategoryColorHex,
|
||||
type Measure,
|
||||
} from '@/lib/units/units';
|
||||
import { getHistory, getFavorites } from '@/lib/units/storage';
|
||||
import { getFavorites } from '@/lib/units/storage';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
interface CommandPaletteProps {
|
||||
|
||||
@@ -2,63 +2,7 @@
|
||||
* LocalStorage utilities for persisting user data
|
||||
*/
|
||||
|
||||
export interface ConversionRecord {
|
||||
id: string;
|
||||
timestamp: number;
|
||||
from: {
|
||||
value: number;
|
||||
unit: string;
|
||||
};
|
||||
to: {
|
||||
value: number;
|
||||
unit: string;
|
||||
};
|
||||
measure: string;
|
||||
}
|
||||
|
||||
const HISTORY_KEY = 'units-ui-history';
|
||||
const FAVORITES_KEY = 'units-ui-favorites';
|
||||
const MAX_HISTORY = 50;
|
||||
|
||||
/**
|
||||
* Save conversion to history
|
||||
*/
|
||||
export function saveToHistory(record: Omit<ConversionRecord, 'id' | 'timestamp'>): void {
|
||||
if (typeof window === 'undefined') return;
|
||||
|
||||
const history = getHistory();
|
||||
const newRecord: ConversionRecord = {
|
||||
...record,
|
||||
id: crypto.randomUUID(),
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
|
||||
// Add to beginning and limit size
|
||||
const updated = [newRecord, ...history].slice(0, MAX_HISTORY);
|
||||
localStorage.setItem(HISTORY_KEY, JSON.stringify(updated));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get conversion history
|
||||
*/
|
||||
export function getHistory(): ConversionRecord[] {
|
||||
if (typeof window === 'undefined') return [];
|
||||
|
||||
try {
|
||||
const stored = localStorage.getItem(HISTORY_KEY);
|
||||
return stored ? JSON.parse(stored) : [];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear conversion history
|
||||
*/
|
||||
export function clearHistory(): void {
|
||||
if (typeof window === 'undefined') return;
|
||||
localStorage.removeItem(HISTORY_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get favorite units
|
||||
|
||||
Reference in New Issue
Block a user