openreplay/frontend/app/components/DataManagement/UsersEvents/UserPage.tsx
2025-02-18 09:13:15 +01:00

210 lines
6.4 KiB
TypeScript

import React from 'react';
import EventDetailsModal, { Triangle } from '../Activity/EventDetailsModal';
import User from './data/User';
import { Dropdown, Popover } from 'antd';
import { MoreOutlined, DeleteOutlined } from '@ant-design/icons';
import Event from 'Components/DataManagement/Activity/data/Event';
import { Files, Users, Eye, EyeOff } from 'lucide-react';
import copy from 'copy-to-clipboard';
import { list } from '../Activity/Page';
import Select from 'Shared/Select';
import { tsToCheckRecent } from 'App/date';
import { useModal } from 'App/components/Modal';
import UserPropertiesModal from './components/UserPropertiesModal';
import Tag from './components/Tag';
import EventsByDay from './components/EventsByDay';
import Breadcrumb from 'Shared/Breadcrumb';
import { dataManagement } from 'App/routes'
const card = 'rounded-lg border bg-white';
function UserPage() {
return (
<div className={'flex flex-col gap-2 mx-auto'} style={{ maxWidth: 1360 }}>
<UserInfo />
<Activity />
</div>
);
}
function Activity() {
const testEvs = [...list, ...list, ...list];
const [show, setShow] = React.useState(true);
const { showModal, hideModal } = useModal();
const onItemClick = (ev: Event) => {
showModal(<EventDetailsModal ev={ev} onClose={hideModal} />, {
width: 420,
right: true,
});
};
const byDays: Record<string, Event[]> = testEvs.reduce((acc, ev) => {
const date = tsToCheckRecent(ev.time, 'LLL dd, yyyy');
if (!acc[date]) {
acc[date] = [];
}
acc[date].push(ev);
return acc;
}, {});
const toggleEvents = () => {
setShow((prev) => !prev);
};
return (
<div className={card}>
<div className={'px-4 py-2 flex items-center gap-2'}>
<div className={'text-lg font-semibold'}>Activity</div>
<div className={'link flex gap-1 items-center'}>
<span>Play Sessions</span>
<Triangle size={10} color={'blue'} />
</div>
<div className={'ml-auto'} />
<div
className={'flex items-center gap-2 cursor-pointer'}
onClick={toggleEvents}
>
{!show ? <Eye size={16} /> : <EyeOff size={16} />}
<span className={'font-medium'}>{show ? 'Hide' : 'Show'} Events</span>
</div>
<Select
options={[
{ label: 'Newest', value: 'DESC' },
{ label: 'Oldest', value: 'ASC' },
]}
defaultValue={'DESC'}
plain
onChange={({ value }) => {
console.log(value);
}}
/>
</div>
<div className={show ? 'block' : 'hidden'}>
<EventsByDay byDays={byDays} onItemClick={onItemClick} />
</div>
</div>
);
}
function UserInfo() {
const { showModal, hideModal } = useModal();
const testUser = new User({
name: 'test user',
userId: 'test@email.com',
distinctId: ['123123123123', '123123123123', '123123123123'],
userLocation: 'NY',
cohorts: ['test'],
properties: {
email: 'test@test.com',
},
updatedAt: Date.now(),
});
const dropdownItems = [
{
label: 'Delete User',
key: 'delete-user',
icon: <DeleteOutlined />,
onClick: () => console.log('confirm'),
},
];
const showAll = () => {
showModal(<UserPropertiesModal properties={testUser.properties} />, {
width: 420,
right: true,
});
};
return (
<>
<Breadcrumb items={[
{ label: 'Users', to: dataManagement.users(), withSiteId: true },
{ label: testUser.name },
]} />
<div className={card}>
<div className="flex items-center justify-between p-4 border-b">
<div className="flex items-center gap-2">
<div
className={
'bg-gray-lighter h-11 w-12 rounded-full flex items-center justify-center text-gray-medium border border-gray-medium'
}
>
{testUser.name.slice(0, 2)}
</div>
<div className="flex flex-col">
<div className="text-xl font-semibold">{testUser.name}</div>
<div>{testUser.userId}</div>
</div>
</div>
<div className="flex flex-col">
<div className={'font-semibold'}>Distinct ID</div>
<div>
{testUser.distinctId[0]}
{testUser.distinctId.length > 1 && (
<Popover
title={
<div className={'text-disabled-text'}>
Tracking IDs linked to this user
</div>
}
trigger={'click'}
placement={'bottom'}
arrow={false}
content={
<div className={'flex flex-col gap-2'}>
{testUser.distinctId.map((id) => (
<div className={'w-full group flex justify-between'}>
<span>{id}</span>
<div
className={
'hidden group-hover:block cursor-pointer active:text-blue'
}
onClick={() => copy(id)}
>
<Files size={14} />
</div>
</div>
))}
</div>
}
>
<div className={'w-fit cursor-pointer inline-block ml-2'}>
<Tag>+{testUser.distinctId.length - 1}</Tag>
</div>
</Popover>
)}
</div>
</div>
<div className="flex flex-col">
<div className={'font-semibold'}>Location</div>
<div>{testUser.userLocation}</div>
</div>
<div className={'flex items-center gap-4'}>
<div onClick={showAll} className={'link font-semibold'}>
+{Object.keys(testUser.properties).length} properties
</div>
<Dropdown
menu={{ items: dropdownItems }}
trigger={['click']}
placement={'bottomRight'}
>
<div className={'cursor-pointer'}>
<MoreOutlined />
</div>
</Dropdown>
</div>
</div>
<div className="flex items-center p-4">
<Users size={14} />
<div className={'mr-4 ml-2'}>Cohorts</div>
{testUser.cohorts.map((cohort) => (
<Tag>{cohort}</Tag>
))}
</div>
</div>
</>
);
}
export default UserPage;