web: added interval minute, profile list and profile view
This commit is contained in:
@@ -16,7 +16,9 @@ export function usePagination(take = 100) {
|
||||
);
|
||||
}
|
||||
|
||||
export function Pagination(props: ReturnType<typeof usePagination>) {
|
||||
export type PaginationProps = ReturnType<typeof usePagination>
|
||||
|
||||
export function Pagination(props: PaginationProps) {
|
||||
return (
|
||||
<div className="flex select-none items-center justify-end space-x-2 py-4">
|
||||
<Button
|
||||
|
||||
99
apps/web/src/components/events/EventsTable.tsx
Normal file
99
apps/web/src/components/events/EventsTable.tsx
Normal file
@@ -0,0 +1,99 @@
|
||||
import { useMemo } from "react";
|
||||
import { DataTable } from "@/components/DataTable";
|
||||
import { type PaginationProps, Pagination } from "@/components/Pagination";
|
||||
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
|
||||
import { Table, TableBody, TableCell, TableRow } from "@/components/ui/table";
|
||||
import { type RouterOutputs } from "@/utils/api";
|
||||
import { formatDateTime } from "@/utils/date";
|
||||
import { toDots } from "@/utils/object";
|
||||
import { AvatarImage } from "@radix-ui/react-avatar";
|
||||
import { createColumnHelper } from "@tanstack/react-table";
|
||||
import Link from "next/link";
|
||||
import { useOrganizationParams } from "@/hooks/useOrganizationParams";
|
||||
|
||||
const columnHelper =
|
||||
createColumnHelper<RouterOutputs["event"]["list"][number]>();
|
||||
|
||||
type EventsTableProps = {
|
||||
data: RouterOutputs["event"]["list"];
|
||||
pagination: PaginationProps;
|
||||
};
|
||||
|
||||
export function EventsTable({ data, pagination }: EventsTableProps) {
|
||||
const params = useOrganizationParams()
|
||||
const columns = useMemo(() => {
|
||||
return [
|
||||
columnHelper.accessor((row) => row.createdAt, {
|
||||
id: "createdAt",
|
||||
header: () => "Created At",
|
||||
cell(info) {
|
||||
return formatDateTime(info.getValue());
|
||||
},
|
||||
footer: () => "Created At",
|
||||
}),
|
||||
columnHelper.accessor((row) => row.name, {
|
||||
id: "event",
|
||||
header: () => "Event",
|
||||
cell(info) {
|
||||
return <span className="font-medium">{info.getValue()}</span>;
|
||||
},
|
||||
footer: () => "Created At",
|
||||
}),
|
||||
columnHelper.accessor((row) => row.profile, {
|
||||
id: "profile",
|
||||
header: () => "Profile",
|
||||
cell(info) {
|
||||
const profile = info.getValue();
|
||||
return (
|
||||
<Link href={`/${params.organization}/${params.project}/profiles/${profile?.id}`} className="flex items-center gap-2">
|
||||
<Avatar className="h-6 w-6">
|
||||
{profile?.avatar && <AvatarImage src={profile.avatar} />}
|
||||
<AvatarFallback className="text-xs">
|
||||
{profile?.first_name?.at(0)}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
{`${profile?.first_name} ${profile?.last_name ?? ""}`}
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
footer: () => "Created At",
|
||||
}),
|
||||
columnHelper.accessor((row) => row.properties, {
|
||||
id: "properties",
|
||||
header: () => "Properties",
|
||||
cell(info) {
|
||||
const dots = toDots(info.getValue() as Record<string, any>);
|
||||
return (
|
||||
<Table className="mini">
|
||||
<TableBody>
|
||||
{Object.keys(dots).map((key) => {
|
||||
return (
|
||||
<TableRow key={key}>
|
||||
<TableCell className="font-medium">{key}</TableCell>
|
||||
<TableCell>
|
||||
{typeof dots[key] === "boolean"
|
||||
? dots[key]
|
||||
? "true"
|
||||
: "false"
|
||||
: dots[key]}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
</TableBody>
|
||||
</Table>
|
||||
);
|
||||
},
|
||||
footer: () => "Created At",
|
||||
}),
|
||||
];
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Pagination {...pagination} />
|
||||
<DataTable data={data} columns={columns} />
|
||||
<Pagination {...pagination} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -7,6 +7,8 @@ export function NavbarMenu() {
|
||||
return (
|
||||
<div className="flex gap-6 items-center">
|
||||
<Link href={`/${params.organization}`}>Home</Link>
|
||||
{params.project && <Link href={`/${params.organization}/${params.project}/events`}>Events</Link>}
|
||||
{params.project && <Link href={`/${params.organization}/${params.project}/profiles`}>Profiles</Link>}
|
||||
<NavbarCreate />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -3,7 +3,7 @@ import { RadioGroup, RadioGroupItem } from "../ui/radio-group";
|
||||
import { changeDateRanges, changeInterval } from "./reportSlice";
|
||||
import { Combobox } from "../ui/combobox";
|
||||
import { type IInterval } from "@/types";
|
||||
import { timeRanges } from "@/utils/constants";
|
||||
import { intervals, timeRanges } from "@/utils/constants";
|
||||
|
||||
export function ReportDateRange() {
|
||||
const dispatch = useDispatch();
|
||||
@@ -14,7 +14,7 @@ export function ReportDateRange() {
|
||||
return (
|
||||
<>
|
||||
<RadioGroup>
|
||||
{timeRanges.map(item => {
|
||||
{timeRanges.map((item) => {
|
||||
return (
|
||||
<RadioGroupItem
|
||||
key={item.range}
|
||||
@@ -25,7 +25,7 @@ export function ReportDateRange() {
|
||||
>
|
||||
{item.title}
|
||||
</RadioGroupItem>
|
||||
)
|
||||
);
|
||||
})}
|
||||
</RadioGroup>
|
||||
{chartType === "linear" && (
|
||||
@@ -36,20 +36,10 @@ export function ReportDateRange() {
|
||||
dispatch(changeInterval(value as IInterval));
|
||||
}}
|
||||
value={interval}
|
||||
items={[
|
||||
{
|
||||
label: "Hour",
|
||||
value: "hour",
|
||||
},
|
||||
{
|
||||
label: "Day",
|
||||
value: "day",
|
||||
},
|
||||
{
|
||||
label: "Month",
|
||||
value: "month",
|
||||
},
|
||||
]}
|
||||
items={Object.entries(intervals).map(([key, value]) => ({
|
||||
label: value,
|
||||
value: key,
|
||||
}))}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useFormatDateInterval } from "@/hooks/useFormatDateInterval";
|
||||
import { useMappings } from "@/hooks/useMappings";
|
||||
import { useSelector } from "@/redux";
|
||||
import { type IToolTipProps } from "@/types";
|
||||
import { formatDate } from "@/utils/date";
|
||||
|
||||
type ReportLineChartTooltipProps = IToolTipProps<{
|
||||
color: string;
|
||||
@@ -17,6 +18,8 @@ export function ReportLineChartTooltip({
|
||||
payload,
|
||||
}: ReportLineChartTooltipProps) {
|
||||
const getLabel = useMappings();
|
||||
const interval = useSelector((state) => state.report.interval);
|
||||
const formatDate = useFormatDateInterval(interval);
|
||||
|
||||
if (!active || !payload) {
|
||||
return null;
|
||||
|
||||
@@ -117,7 +117,9 @@ export const reportSlice = createSlice({
|
||||
|
||||
changeDateRanges: (state, action: PayloadAction<IChartRange>) => {
|
||||
state.range = action.payload
|
||||
if (action.payload === 0 || action.payload === 1) {
|
||||
if (action.payload === 0.3 || action.payload === 0.6) {
|
||||
state.interval = "minute";
|
||||
} else if (action.payload === 0 || action.payload === 1) {
|
||||
state.interval = "hour";
|
||||
} else if (action.payload <= 30) {
|
||||
state.interval = "day";
|
||||
|
||||
Reference in New Issue
Block a user