-
Notifications
You must be signed in to change notification settings - Fork 1.9k
feat(ui): add new findings table #9699
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 17 commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
d6b8346
feat: add new findings table cell components
alejandrobailo 0ca9964
feat: redesign shadcn checkbox and select components
alejandrobailo 018ad9f
feat: update table components with new design system
alejandrobailo 300666e
feat: refactor findings table columns and details
alejandrobailo 34d9360
feat: add toggle functionality to filter controls
alejandrobailo 130d1a9
feat: add shadcn calendar component with react-day-picker
alejandrobailo 033f726
feat: add data-table-search component with toolbar
alejandrobailo e045c99
feat: redesign date picker and clear filters button
alejandrobailo efe4d4b
feat: refactor findings filters with provider selectors
alejandrobailo 880ec5c
feat: enable search in findings table
alejandrobailo ef8fccc
feat: add expandable animation to data-table-search
alejandrobailo 3bb4a5e
chore: CHANGELOG.md updated
alejandrobailo 58c9eb9
feat: filters expand with animation and delta tooltip
alejandrobailo 13bf004
fix: filters spacing
alejandrobailo b553ff6
fix: lint issues
alejandrobailo 0e8001f
Merge branch 'master' into feat/PROWLER-379-new-table
alejandrobailo 051471e
refactor: improve code quality
alejandrobailo e3f076e
fix: PR comments
alejandrobailo 74fd3f2
fix: different account filter param for overview and findings
alejandrobailo 771b45e
feat: skeleton for findings table
alejandrobailo 32a5e93
style: search bar border color
alejandrobailo ede82e8
build: format issues
alejandrobailo 892cbe4
fix: account filter param diff (#9701)
alejandrobailo 5c85ee6
feat: new finding detail view (#9727)
alejandrobailo af68429
fix: lint issues
alejandrobailo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,120 +1,93 @@ | ||
| "use client"; | ||
|
|
||
| import { Button, ButtonGroup } from "@heroui/button"; | ||
| import { DatePicker } from "@heroui/date-picker"; | ||
| import { | ||
| getLocalTimeZone, | ||
| parseDate, | ||
| startOfMonth, | ||
| startOfWeek, | ||
| today, | ||
| } from "@internationalized/date"; | ||
| import { useLocale } from "@react-aria/i18n"; | ||
| import type { DateValue } from "@react-types/datepicker"; | ||
| import { format } from "date-fns"; | ||
| import { CalendarIcon, ChevronDown } from "lucide-react"; | ||
| import { useSearchParams } from "next/navigation"; | ||
| import { useEffect, useRef, useState } from "react"; | ||
| import { useEffect, useState } from "react"; | ||
|
|
||
| import { Calendar } from "@/components/shadcn/calendar"; | ||
| import { | ||
| Popover, | ||
| PopoverContent, | ||
| PopoverTrigger, | ||
| } from "@/components/shadcn/popover"; | ||
| import { useUrlFilters } from "@/hooks/use-url-filters"; | ||
| import { cn } from "@/lib/utils"; | ||
|
|
||
| export const CustomDatePicker = () => { | ||
| const searchParams = useSearchParams(); | ||
| const { updateFilter } = useUrlFilters(); | ||
| const [open, setOpen] = useState(false); | ||
|
|
||
| const [value, setValue] = useState<DateValue | null>(() => { | ||
| const [date, setDate] = useState<Date | undefined>(() => { | ||
| const dateParam = searchParams.get("filter[inserted_at]"); | ||
| if (!dateParam) return null; | ||
| if (!dateParam) return undefined; | ||
| try { | ||
| return parseDate(dateParam); | ||
| return new Date(dateParam); | ||
| } catch { | ||
| return null; | ||
| return undefined; | ||
| } | ||
| }); | ||
|
|
||
| const { locale } = useLocale(); | ||
|
|
||
| const now = today(getLocalTimeZone()); | ||
| const nextWeek = startOfWeek(now.add({ weeks: 1 }), locale); | ||
| const nextMonth = startOfMonth(now.add({ months: 1 })); | ||
|
|
||
| const applyDateFilter = (date: DateValue | null) => { | ||
| if (date) { | ||
| updateFilter("inserted_at", date.toString()); | ||
| const applyDateFilter = (selectedDate: Date | undefined) => { | ||
| if (selectedDate) { | ||
| // Format as YYYY-MM-DD for the API | ||
| updateFilter("inserted_at", format(selectedDate, "yyyy-MM-dd")); | ||
| } else { | ||
| updateFilter("inserted_at", null); | ||
| } | ||
| }; | ||
|
|
||
| const initialRender = useRef(true); | ||
|
|
||
| // Sync local state with URL params (e.g., when Clear Filters is clicked) | ||
| useEffect(() => { | ||
| if (initialRender.current) { | ||
| initialRender.current = false; | ||
| return; | ||
| } | ||
| const params = new URLSearchParams(searchParams.toString()); | ||
| if (params.size === 0) { | ||
| setValue(null); | ||
| const dateParam = searchParams.get("filter[inserted_at]"); | ||
| if (!dateParam) { | ||
| setDate(undefined); | ||
| } else { | ||
| try { | ||
| setDate(new Date(dateParam)); | ||
| } catch { | ||
| setDate(undefined); | ||
| } | ||
| } | ||
| }, [searchParams]); | ||
|
|
||
| const handleDateChange = (newValue: DateValue | null) => { | ||
| setValue(newValue); | ||
| applyDateFilter(newValue); | ||
| const handleDateSelect = (newDate: Date | undefined) => { | ||
| setDate(newDate); | ||
| applyDateFilter(newDate); | ||
| setOpen(false); | ||
| }; | ||
|
|
||
| return ( | ||
| <div className="flex w-full flex-col md:gap-2"> | ||
| <DatePicker | ||
| style={{ | ||
| borderRadius: "0.5rem", | ||
| }} | ||
| aria-label="Select a Date" | ||
| classNames={{ | ||
| base: "w-full [&]:!rounded-lg [&>*]:!rounded-lg", | ||
| selectorButton: "text-bg-button-secondary shrink-0", | ||
| input: | ||
| "text-bg-button-secondary placeholder:text-bg-button-secondary text-sm", | ||
| innerWrapper: "[&]:!rounded-lg", | ||
| inputWrapper: | ||
| "!border-border-input-primary !bg-bg-input-primary dark:!bg-input/30 dark:hover:!bg-input/50 hover:!bg-bg-neutral-secondary !border [&]:!rounded-lg !shadow-xs !transition-[color,box-shadow] focus-within:!border-border-input-primary-press focus-within:!ring-1 focus-within:!ring-border-input-primary-press focus-within:!ring-offset-1 !h-10 !px-4 !py-3 !outline-none", | ||
| segment: "text-bg-button-secondary", | ||
| }} | ||
| popoverProps={{ | ||
| classNames: { | ||
| content: | ||
| "border-border-input-primary bg-bg-input-primary border rounded-lg", | ||
| }, | ||
| }} | ||
| CalendarTopContent={ | ||
| <ButtonGroup | ||
| fullWidth | ||
| className="bg-bg-neutral-secondary [&>button]:border-border-neutral-secondary [&>button]:text-bg-button-secondary px-3 pt-3 pb-2" | ||
| radius="full" | ||
| size="sm" | ||
| variant="flat" | ||
| > | ||
| <Button onPress={() => handleDateChange(now)}>Today</Button> | ||
| <Button onPress={() => handleDateChange(nextWeek)}> | ||
| Next week | ||
| </Button> | ||
| <Button onPress={() => handleDateChange(nextMonth)}> | ||
| Next month | ||
| </Button> | ||
| </ButtonGroup> | ||
| } | ||
| calendarProps={{ | ||
| focusedValue: value || undefined, | ||
| onFocusChange: setValue, | ||
| nextButtonProps: { | ||
| variant: "bordered", | ||
| }, | ||
| prevButtonProps: { | ||
| variant: "bordered", | ||
| }, | ||
| }} | ||
| value={value} | ||
| onChange={handleDateChange} | ||
| /> | ||
| </div> | ||
| <Popover open={open} onOpenChange={setOpen}> | ||
| <PopoverTrigger asChild> | ||
| <button | ||
| type="button" | ||
| aria-haspopup="dialog" | ||
| aria-expanded={open} | ||
| className={cn( | ||
| "border-border-input-primary bg-bg-input-primary text-bg-button-secondary dark:bg-input/30 dark:hover:bg-input/50 focus-visible:border-border-input-primary-press focus-visible:ring-border-input-primary-press flex h-[52px] w-full items-center justify-between gap-2 rounded-lg border px-4 py-3 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-1 focus-visible:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0", | ||
| !date && "text-bg-button-secondary", | ||
| )} | ||
| > | ||
| <span className="flex items-center gap-2"> | ||
| <CalendarIcon className="text-bg-button-secondary size-5 opacity-70" /> | ||
| {date ? format(date, "PPP") : "Pick a date"} | ||
| </span> | ||
| <ChevronDown | ||
| className={cn( | ||
| "text-bg-button-secondary size-6 shrink-0 opacity-70 transition-transform duration-200", | ||
| open && "rotate-180", | ||
| )} | ||
| /> | ||
| </button> | ||
| </PopoverTrigger> | ||
| <PopoverContent | ||
| className="border-border-input-primary bg-bg-input-primary w-auto p-0" | ||
| align="start" | ||
| > | ||
| <Calendar mode="single" selected={date} onSelect={handleDateSelect} /> | ||
| </PopoverContent> | ||
| </Popover> | ||
| ); | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.