add: chat radar page
This commit is contained in:
@@ -1,16 +1,134 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react'
|
||||
import { motion } from 'framer-motion';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
|
||||
type Props = object
|
||||
const users = [
|
||||
{ id: 0, name: '1 علی مصلحی', table: 12, avatar: '/assets/images/user-avatar.png' },
|
||||
{ id: 1, name: '2 علی مصلحی', table: 10, avatar: '/assets/images/user-avatar.png' },
|
||||
{ id: 2, name: '3 علی مصلحی', table: 11, avatar: '/assets/images/user-avatar.png' },
|
||||
{ id: 3, name: '4 علی مصلحی', table: 5, avatar: '/assets/images/user-avatar.png' },
|
||||
{ id: 4, name: '5 علی مصلحی', table: 2, avatar: '/assets/images/user-avatar.png' },
|
||||
{ id: 5, name: '6 علی مصلحی', table: 1, avatar: '/assets/images/user-avatar.png' },
|
||||
];
|
||||
|
||||
function ChatIndex() {
|
||||
const containerRef = useRef<HTMLElement>(null);
|
||||
const [positions, setPositions] = useState<{ top: number; left: number }[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (containerRef.current) {
|
||||
const maxW = containerRef.current.offsetWidth - 50;
|
||||
const maxH = containerRef.current.offsetHeight - 80;
|
||||
const elementSize = 110; // approximate size of each user element
|
||||
const padding = 80; // minimum distance between elements
|
||||
|
||||
const positions: { top: number; left: number }[] = [];
|
||||
|
||||
const isTooClose = (top: number, left: number) => {
|
||||
return positions.some(p => {
|
||||
const dx = p.left - left;
|
||||
const dy = p.top - top;
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
return distance < padding;
|
||||
});
|
||||
};
|
||||
|
||||
users.forEach(() => {
|
||||
let top = 0;
|
||||
let left = 0;
|
||||
let tries = 0;
|
||||
|
||||
do {
|
||||
top = Math.random() * (maxH - elementSize);
|
||||
left = Math.random() * (maxW - elementSize);
|
||||
tries++;
|
||||
} while (isTooClose(top, left) && tries < 100);
|
||||
|
||||
positions.push({ top, left });
|
||||
});
|
||||
|
||||
setPositions(positions);
|
||||
}
|
||||
}, []);
|
||||
|
||||
function ChatIndex({ }: Props) {
|
||||
|
||||
return (
|
||||
<section className='h-full pb-8'>
|
||||
TODO
|
||||
<section ref={containerRef} className="h-full pb-8 relative overflow-hidden">
|
||||
<section className="relative h-full w-full mt-7">
|
||||
<motion.div
|
||||
animate={{ scale: [1, 0.95, 1] }}
|
||||
transition={{ repeat: Infinity, duration: 13 }}
|
||||
className='size-[824px] rounded-full fixed top-1/2 left-1/2 -translate-1/2'
|
||||
style={{ background: 'linear-gradient(180deg, #EBF0FC 4.52%, #EBF0FC 95.02%)', willChange: 'transform' }}
|
||||
>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
animate={{ scale: [0.9, 1] }}
|
||||
transition={{ repeat: Infinity, duration: 4, repeatType: 'reverse' }}
|
||||
className='size-[617px] rounded-full fixed top-1/2 left-1/2 -translate-1/2'
|
||||
style={{ background: 'linear-gradient(180deg, #E6EBFA 0%, #DFE2EC 100%)', willChange: 'transform' }}
|
||||
>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
animate={{ scale: [1.02, 0.95] }}
|
||||
transition={{ repeat: Infinity, duration: 2, repeatType: 'reverse' }}
|
||||
className='size-[425px] rounded-full fixed top-1/2 left-1/2 -translate-1/2'
|
||||
style={{ background: 'linear-gradient(180deg, #E1E5EF 0%, #D8DDE8 60.2%, #D2D7E3 100%)', willChange: 'transform' }}
|
||||
>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
animate={{ scale: [1.05, 1] }}
|
||||
transition={{ repeat: Infinity, duration: 2, repeatType: 'reverse' }}
|
||||
className='size-[292px] rounded-full fixed top-1/2 left-1/2 -translate-1/2'
|
||||
style={{ background: 'linear-gradient(180deg, #EAEDF5 0%, #E4E7F0 46.52%, #DDDFEB 100%)', willChange: 'transform' }}
|
||||
>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
animate={{ scale: [1, 1.05] }}
|
||||
transition={{ repeat: Infinity, duration: 2, repeatType: 'reverse' }}
|
||||
|
||||
className='size-[174px] rounded-full fixed top-1/2 left-1/2 -translate-1/2'
|
||||
style={{ background: 'linear-gradient(180deg, #F3F7FF 0%, #F2F5FC 100%)', willChange: 'transform' }}
|
||||
>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
animate={{ scale: [0, 1.2], opacity: [1, 0] }}
|
||||
transition={{ repeat: Infinity, duration: 2 }}
|
||||
|
||||
className='h-full w-dvh rounded-full fixed top-1/2 left-1/2 -translate-1/2 outline outline-solid outline-blue-400'
|
||||
style={{ willChange: 'transform, opacity' }}
|
||||
>
|
||||
</motion.div>
|
||||
|
||||
<div className='grid grid-cols-6 grid-rows-6'>
|
||||
{positions.length === users.length &&
|
||||
users.map((v, i) => (
|
||||
<Link
|
||||
href={`chat/${v.id}`}
|
||||
prefetch={false}
|
||||
key={v.id}
|
||||
style={{ position: 'absolute', top: positions[i].top, left: positions[i].left }}
|
||||
className="justify-items-center"
|
||||
>
|
||||
<Image height={46} width={46} alt="user avatar" src={v.avatar} />
|
||||
<h6 className="mt-2 text-xs font-medium">{v.name}</h6>
|
||||
<div className="mt-[3px] text-xs2 font-medium bg-disabled-text text-accent rounded-[5px] px-[5px] py-[3px]">
|
||||
میز {v.table}
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default ChatIndex
|
||||
export default ChatIndex;
|
||||
|
||||
Reference in New Issue
Block a user