Skip to content

Commit

Permalink
feat: add custom time and calendar
Browse files Browse the repository at this point in the history
  • Loading branch information
ogzhanolguncu committed Sep 28, 2024
1 parent 78eec7b commit 20ea6ae
Show file tree
Hide file tree
Showing 7 changed files with 267 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"use client";

import { addDays, format } from "date-fns";
import * as React from "react";
import type { DateRange } from "react-day-picker";

import { Calendar } from "@/components/ui/calendar";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { cn } from "@/lib/utils";
import { Calendar as CalendarIcon } from "lucide-react";

const currentDate = new Date();
export function DatePickerWithRange({
className,
}: React.HTMLAttributes<HTMLDivElement>) {
const [date, setDate] = React.useState<DateRange | undefined>({
from: currentDate,
to: addDays(currentDate, 20),
});

return (
<div className={cn("grid gap-2", className)}>
<Popover>
<PopoverTrigger asChild>
<div
id="date"
className={cn(
"w-fit justify-start text-left font-normal flex gap-2 items-center",
!date && "text-muted-foreground"
)}
>
<CalendarIcon className="h-4 w-4" />
{date?.from ? (
date.to ? (
<>
{format(date.from, "LLL dd, y")} -{" "}
{format(date.to, "LLL dd, y")}
</>
) : (
format(date.from, "LLL dd, y")
)
) : (
<span>Pick a date</span>
)}
</div>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
initialFocus
mode="range"
defaultMonth={date?.from}
selected={date}
onSelect={setDate}
numberOfMonths={2}
/>
</PopoverContent>
</Popover>
</div>
);
}
81 changes: 81 additions & 0 deletions apps/dashboard/app/(app)/logs/filters/components/hour-filter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
"use client";

import {
Command,
CommandGroup,
CommandItem,
CommandList,
} from "@/components/ui/command";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { cn } from "@/lib/utils";
import { Check, Clock } from "lucide-react";
import { useState } from "react";

const options = [
{
value: "1h",
label: "Last hours",
},
{
value: "3h",
label: "Last 3 hours",
},
{
value: "6h",
label: "Last 6 hours",
},
{
value: "12h",
label: "Last 12 hours",
},
{
value: "24h",
label: "Last 24 hours",
},
];

export function HourFilter() {
const [open, setOpen] = useState(false);
const [value, setValue] = useState("1h");

return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<div className="flex gap-2 items-center justify-center">
<Clock className="h-4 w-4" />
{options.find((o) => o.value === value)?.label}
</div>
</PopoverTrigger>
<PopoverContent className="w-[200px] p-0">
<Command>
<CommandList>
<CommandGroup>
{options.map((option) => (
<CommandItem
key={option.value}
value={option.value}
onSelect={(currentValue) => {
setValue(currentValue === value ? "" : currentValue);
setOpen(false);
}}
>
<Check
className={cn(
"mr-2 h-4 w-4",
value === option.value ? "opacity-100" : "opacity-0"
)}
/>
{option.label}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
);
}
38 changes: 38 additions & 0 deletions apps/dashboard/app/(app)/logs/filters/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"use client";

import { Button } from "@/components/ui/button";
import { ButtonGroup } from "@/components/ui/group-button";
import { Input } from "@/components/ui/input";
import { RefreshCcw, Search } from "lucide-react";
import { ChartsComp } from "../chart";
import { DatePickerWithRange } from "./components/custom-date-filter";
import { HourFilter } from "./components/hour-filter";

export const LogFilters = () => {
return (
<>
<div className="flex items-center gap-2 w-full">
<div className="w-[330px]">
<Input type="text" placeholder="Search logs" startIcon={Search} />
</div>
<Button variant="outline" size="icon" className="w-10">
<RefreshCcw className="h-4 w-4" />
</Button>
<ButtonGroup>
<Button variant="outline">
<HourFilter />
</Button>
<Button variant="outline">
<DatePickerWithRange />
</Button>
</ButtonGroup>

<ButtonGroup>
<Button variant="outline">Response Status</Button>
<Button variant="outline">Request ID</Button>
</ButtonGroup>
</div>
<ChartsComp />
</>
);
};
39 changes: 3 additions & 36 deletions apps/dashboard/app/(app)/logs/page.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
"use client";

import { Button } from "@/components/ui/button";
import { ButtonGroup } from "@/components/ui/group-button";
import { Input } from "@/components/ui/input";
import { ScrollArea } from "@/components/ui/scroll-area";
import { cn } from "@/lib/utils";
import { ScrollArea } from "@radix-ui/react-scroll-area";
import { format } from "date-fns";
import { Calendar, Clock, RefreshCcw, Search } from "lucide-react";
import { useState } from "react";
import { ChartsComp } from "./chart";
import { RED_STATES, YELLOW_STATES } from "./constants";
import { type Log, sampleLogs } from "./data";
import { LogFilters } from "./filters";
import { LogDetails } from "./log-details";
import { getOutcomeIfValid } from "./utils";

Expand All @@ -21,35 +17,7 @@ export default function Page() {

return (
<div className="flex flex-col gap-4 items-start w-full overflow-y-hidden">
{/* Filter Section */}
<div className="flex items-center gap-2 w-full">
<div className="w-[330px]">
<Input type="text" placeholder="Search logs" startIcon={Search} />
</div>
<Button variant="outline" size="icon" className="w-10">
<RefreshCcw className="h-4 w-4" />
</Button>
<ButtonGroup>
<Button variant="outline">
<Clock className="h-4 w-4" />
Last hour
</Button>
<Button variant="outline">
{" "}
<Calendar className="h-4 w-4" />
Custom
</Button>
</ButtonGroup>

<ButtonGroup>
<Button variant="outline">Response Status</Button>
<Button variant="outline">Request ID</Button>
<Button variant="outline">Api ID</Button>
<Button variant="outline">Key ID</Button>
</ButtonGroup>
</div>
<ChartsComp />
{/* Logs section */}
<LogFilters />
<div className="w-full">
<div className="grid grid-cols-[166px_72px_12%_calc(20%+32px)_1fr] text-sm font-medium text-[#666666]">
<div className="p-2 flex items-center">Time</div>
Expand All @@ -59,7 +27,6 @@ export default function Page() {
<div className="p-2 flex items-center">Message</div>
</div>
<div className="w-full border-t border-border" />
{/* TODO fix overflow issue */}
<ScrollArea className="h-[75vh]">
{sampleLogs.map((log, index) => {
const outcome = getOutcomeIfValid(log);
Expand Down
66 changes: 66 additions & 0 deletions apps/dashboard/components/ui/calendar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"use client";

import { ChevronLeft, ChevronRight } from "lucide-react";
import type * as React from "react";
import { DayPicker } from "react-day-picker";

import { buttonVariants } from "@/components/ui/button";
import { cn } from "@/lib/utils";

export type CalendarProps = React.ComponentProps<typeof DayPicker>;

function Calendar({
className,
classNames,
showOutsideDays = true,
...props
}: CalendarProps) {
return (
<DayPicker
showOutsideDays={showOutsideDays}
className={cn("p-3 bg-background rounded-md", className)}
classNames={{
months: "flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0",
month: "space-y-4",
caption: "flex justify-center pt-1 relative items-center",
caption_label: "text-sm font-medium",
nav: "space-x-1 flex items-center",
nav_button: cn(
buttonVariants({ variant: "outline" }),
"h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100"
),
nav_button_previous: "absolute left-1",
nav_button_next: "absolute right-1",
table: "w-full border-collapse space-y-1",
head_row: "flex",
head_cell:
"text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]",
row: "flex w-full mt-2",
cell: "h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20",
day: cn(
buttonVariants({ variant: "ghost" }),
"h-9 w-9 p-0 font-normal aria-selected:opacity-100"
),
day_range_end: "day-range-end",
day_selected:
"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
day_today: "bg-accent text-accent-foreground",
day_outside:
"day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30",
day_disabled: "text-muted-foreground opacity-50",
day_range_middle:
"aria-selected:bg-accent aria-selected:text-accent-foreground",
day_hidden: "invisible",
...classNames,
}}
components={{
IconLeft: () => <ChevronLeft className="h-4 w-4" />,
IconRight: () => <ChevronRight className="h-4 w-4" />,
}}
{...props}
/>
);
}
Calendar.displayName = "Calendar";

export { Calendar };
1 change: 1 addition & 0 deletions apps/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
"posthog-js": "^1.130.1",
"posthog-node": "^4.2.0",
"react": "^18.2.0",
"react-day-picker": "8.10.1",
"react-dom": "^18.2.0",
"react-hook-form": "^7.51.3",
"react-markdown": "^8.0.7",
Expand Down
14 changes: 14 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 20ea6ae

Please sign in to comment.