Reuben_OS / app /components /DraggableDesktopIcon.tsx
Reubencf's picture
Added elevnlabs
163eb99
'use client'
import React, { useState, useRef } from 'react'
import Draggable from 'react-draggable'
import {
Folder,
Calendar,
Clock,
Globe,
Sparkle,
Flask,
DeviceMobile,
Function,
HardDrives,
Code,
Lightning,
Key,
Brain,
ChatCircleDots,
MusicNote
} from '@phosphor-icons/react'
import { DynamicClockIcon } from './DynamicClockIcon'
import { DynamicCalendarIcon } from './DynamicCalendarIcon'
interface DraggableDesktopIconProps {
id: string
label: string
iconType: string
initialPosition?: { x: number; y: number }
onClick: () => void
onDoubleClick: () => void
}
export function DraggableDesktopIcon({
id,
label,
iconType,
initialPosition = { x: 0, y: 0 },
onClick,
onDoubleClick
}: DraggableDesktopIconProps) {
const [selected, setSelected] = useState(false)
const nodeRef = useRef<HTMLDivElement>(null) as React.MutableRefObject<HTMLDivElement>
const handleClick = () => {
setSelected(true)
onClick()
// Deselect after a short time
setTimeout(() => setSelected(false), 3000)
}
const getIcon = () => {
switch (iconType) {
case 'files':
return (
<div className="bg-gradient-to-br from-blue-400 to-cyan-200 w-full h-full rounded-xl flex items-center justify-center border border-white/30">
<Folder size={32} weight="regular" className="text-blue-900" />
</div>
)
case 'calendar':
return (
<div className="w-full h-full">
<DynamicCalendarIcon />
</div>
)
case 'clock':
return (
<div className="w-full h-full">
<DynamicClockIcon />
</div>
)
case 'messages':
return (
<div className="bg-gradient-to-b from-[#4CD964] to-[#2E8B57] w-full h-full rounded-[22%] flex items-center justify-center shadow-lg border-[0.5px] border-white/20 relative overflow-hidden group-hover:shadow-2xl transition-all duration-300">
<div className="absolute inset-0 bg-gradient-to-b from-white/20 to-transparent opacity-50" />
<ChatCircleDots size={36} weight="fill" className="text-white relative z-10 drop-shadow-md" />
</div>
)
case 'flutter':
return (
<div className="bg-gradient-to-b from-[#54C5F8] to-[#29B6F6] w-full h-full rounded-[22%] flex items-center justify-center shadow-lg border-[0.5px] border-white/20 relative overflow-hidden group-hover:shadow-2xl transition-all duration-300">
<div className="absolute inset-0 bg-gradient-to-b from-white/20 to-transparent opacity-50" />
<DeviceMobile size={36} weight="fill" className="text-white relative z-10 drop-shadow-md" />
<div className="absolute top-1.5 right-1.5">
<Lightning size={12} weight="fill" className="text-yellow-300 drop-shadow-md" />
</div>
</div>
)
case 'latex':
return (
<div className="bg-gradient-to-b from-slate-700 to-slate-900 w-full h-full rounded-[22%] flex items-center justify-center shadow-lg border-[0.5px] border-white/20 relative overflow-hidden group-hover:shadow-2xl transition-all duration-300">
<div className="absolute inset-0 bg-gradient-to-b from-white/10 to-transparent opacity-30" />
<div className="relative z-10 flex flex-col items-center justify-center">
<Function size={32} weight="bold" className="text-green-400 drop-shadow-md" />
<span className="text-[8px] font-black text-gray-300 tracking-widest mt-0.5">TEX</span>
</div>
</div>
)
case 'gemini':
return (
<div className="bg-gradient-to-b from-white to-blue-50 w-full h-full rounded-[22%] flex items-center justify-center shadow-lg border-[0.5px] border-white/50 relative overflow-hidden group-hover:shadow-2xl transition-all duration-300">
<div className="absolute inset-0 bg-gradient-to-b from-white/40 to-transparent" />
<Sparkle size={36} weight="fill" className="text-blue-500 relative z-10 drop-shadow-sm" />
</div>
)
case 'harddrive':
return (
<div className="bg-gray-200 w-full h-full rounded-lg flex items-center justify-center border border-gray-300 relative">
<HardDrives size={32} weight="regular" className="text-gray-600" />
<div className="absolute bottom-2 right-2 w-1.5 h-1.5 bg-green-400 rounded-full animate-pulse" />
</div>
)
case 'vscode':
return (
<div className="bg-gradient-to-br from-blue-600 to-blue-800 w-full h-full rounded-xl flex items-center justify-center border border-blue-900/30 shadow-inner">
<Code size={32} weight="bold" className="text-white" />
</div>
)
case 'playground':
return (
<div className="bg-gradient-to-br from-yellow-500 to-orange-600 w-full h-full rounded-xl flex items-center justify-center border border-orange-700/30 shadow-inner">
<Lightning size={32} weight="fill" className="text-white" />
</div>
)
case 'key':
return (
<div className="bg-gradient-to-br from-purple-600 to-purple-800 w-full h-full rounded-xl flex items-center justify-center border border-purple-900/30 shadow-inner">
<Key size={32} weight="bold" className="text-white" />
</div>
)
case 'quiz':
return (
<div className="bg-gradient-to-br from-teal-400 to-emerald-500 w-full h-full rounded-[22%] flex items-center justify-center shadow-lg border-[0.5px] border-white/20 relative overflow-hidden group-hover:shadow-2xl transition-all duration-300">
<div className="absolute inset-0 bg-gradient-to-b from-white/20 to-transparent opacity-50" />
<Brain size={36} weight="fill" className="text-white relative z-10 drop-shadow-md" />
</div>
)
case 'voice-app':
return (
<div className="bg-gradient-to-br from-purple-500 to-pink-500 w-full h-full rounded-[22%] flex items-center justify-center shadow-lg border-[0.5px] border-white/20 relative overflow-hidden group-hover:shadow-2xl transition-all duration-300">
<div className="absolute inset-0 bg-gradient-to-b from-white/20 to-transparent opacity-50" />
<MusicNote size={36} weight="fill" className="text-white relative z-10 drop-shadow-md" />
</div>
)
default:
return (
<div className="bg-gray-400 w-full h-full rounded-xl flex items-center justify-center">
<Folder size={32} weight="regular" className="text-white" />
</div>
)
}
}
return (
<Draggable
nodeRef={nodeRef}
defaultPosition={initialPosition}
grid={[25, 25]}
handle=".icon-handle"
>
<div
ref={nodeRef}
className="absolute flex flex-col items-center w-20 group cursor-pointer transition-all hover:bg-white/10 rounded p-1"
onClick={handleClick}
onDoubleClick={onDoubleClick}
>
<div className="icon-handle">
<div
className={`w-14 h-14 shadow-lg transition-transform hover:scale-110 ${iconType === 'clock' ? '' : 'rounded-xl'
}`}
>
{getIcon()}
</div>
</div>
<span
className={`mt-1 text-xs font-medium drop-shadow-lg text-center leading-tight px-1 py-0.5 rounded transition-colors ${selected
? 'bg-blue-600/80 text-white'
: 'text-white bg-black/20 group-hover:bg-blue-600/80'
}`}
>
{label}
</span>
</div>
</Draggable>
)
}