Skip to content
This repository has been archived by the owner on Oct 31, 2024. It is now read-only.

Commit

Permalink
Integrate category filter to add connection tab
Browse files Browse the repository at this point in the history
  • Loading branch information
Rodrigo Arze Leon authored and Rodrigo Arze Leon committed Oct 25, 2024
1 parent 6805d99 commit 925624c
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 23 deletions.
39 changes: 22 additions & 17 deletions packages/engine-frontend/components/IntegrationSearch.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
'use client'

import {Loader, Search} from 'lucide-react'
import React from 'react'
import {Input} from '@openint/ui'
import React, {useState} from 'react'

Check failure on line 4 in packages/engine-frontend/components/IntegrationSearch.tsx

View workflow job for this annotation

GitHub Actions / Run type checks, lint, and tests

'React' is declared but its value is never read.

Check failure on line 4 in packages/engine-frontend/components/IntegrationSearch.tsx

View workflow job for this annotation

GitHub Actions / Run type checks, lint, and tests

'React' is declared but its value is never read.
import {Input, parseCategory} from '@openint/ui'
import {CheckboxFilter} from '@openint/ui/components/CheckboxFilter'
import {ConnectionCard} from '@openint/ui/domain-components/ConnectionCard'
import type {ConnectorConfig} from '../hocs/WithConnectConfig'
import type {ConnectEventType} from '../hocs/WithConnectorConnect'
Expand All @@ -25,7 +26,8 @@ export function IntegrationSearch({
type: ConnectEventType
}) => void
}) {
const [searchText, setSearchText] = React.useState('')
const [searchText, setSearchText] = useState('')
const [categoryFilter, setCategoryFilter] = useState<string[]>([])

const listIntegrationsRes = _trpcReact.listConfiguredIntegrations.useQuery({
connector_config_ids: connectorConfigs.map((ccfg) => ccfg.id),
Expand All @@ -36,32 +38,43 @@ export function IntegrationSearch({
ccfg: connectorConfigs.find((ccfg) => ccfg.id === int.connector_config_id)!,
}))

const categories = Array.from(
new Set(connectorConfigs.flatMap((ccfg) => ccfg.verticals)),
)

const intsByCategory = ints?.reduce(
(acc, int) => {
int.ccfg.verticals.forEach((vertical) => {
acc[vertical] = (acc[vertical] || []).concat(int)
if (categoryFilter.length === 0 || categoryFilter.includes(vertical)) {
acc[vertical] = (acc[vertical] || []).concat(int)
}
})
return acc
},
{} as Record<string, typeof ints>,
)

const onApplyFilter = (selected: string[]) => {
setCategoryFilter(selected)
}

return (
<div className={className}>
{/* Search integrations */}
<div className="mb-2 bg-background/95 pt-4 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<form>
<div className="relative">
<div className="flex flex-row gap-2">
<div className="relative w-[450px]">
{/* top-2.5 is not working for some reason due to tailwind setup */}
<Search className="absolute left-2 top-2 h-4 w-4 text-muted-foreground" />
<Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
<Input
placeholder="Search"
className="pl-8"
value={searchText}
onChange={(e) => setSearchText(e.target.value)}
/>
</div>
</form>
<CheckboxFilter options={categories} onApply={onApplyFilter} />
</div>
</div>
{/* Search results */}
{listIntegrationsRes.isLoading ? (
Expand All @@ -76,15 +89,7 @@ export function IntegrationSearch({
([category, categoryInts]) => (
<div key={category}>
<h3 className="mb-2 text-lg font-semibold">
{category.length < 5
? category.toUpperCase()
: category
.split('-')
.map(
(word) =>
word.charAt(0).toUpperCase() + word.slice(1),
)
.join(' ')}
{parseCategory(category)}
</h3>
<div className="flex flex-row gap-4">
{categoryInts.map((int) => (
Expand Down
36 changes: 30 additions & 6 deletions packages/ui/components/CheckboxFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import {useState} from 'react'
import {Button} from '../shadcn/Button'
import {Checkbox} from '../shadcn/Checkbox'
import {Popover, PopoverContent, PopoverTrigger} from '../shadcn/Popover'
import {parseCategory} from '../utils'

export function CheckboxFilter({
options,
onApply,
}: {
options: string[]
onApply: () => void
onApply: (selected: string[]) => void
}) {
const [checkedState, setCheckedState] = useState<Record<string, boolean>>(
options.reduce(
Expand Down Expand Up @@ -37,7 +38,7 @@ export function CheckboxFilter({
<span className="ml-2">Category</span>
</Button>
</PopoverTrigger>
<PopoverContent className="w-40 bg-white">
<PopoverContent className="w-48 bg-white">
<div className="flex flex-col gap-2">
{options.map((option) => (
<div
Expand All @@ -58,7 +59,7 @@ export function CheckboxFilter({
<span
className={`block h-4 w-4 rounded-sm ${
checkedState[option]
? 'bg-[#8A7DFF] text-white'
? 'bg-button text-button-foreground'
: 'bg-transparent'
}`}>
{checkedState[option] && (
Expand All @@ -80,14 +81,37 @@ export function CheckboxFilter({
htmlFor={option}
className="cursor-pointer text-sm font-semibold">
{' '}
{option}
{parseCategory(option)}
</label>
</div>
))}
{/* Added a visible divider here */}
<div className="my-2 w-full border-t border-[#E6E6E6]" />
<div className="col-span-3 flex justify-end">
<Button onClick={onApply} size="sm">
<div className="col-span-3 flex justify-end gap-2">
<Button
onClick={() => {
setCheckedState(
options.reduce(
(acc, option) => {
acc[option] = false
return acc
},
{} as Record<string, boolean>,
),
)
onApply([])
}}
size="sm"
variant="secondary">
Clear
</Button>
<Button
onClick={() =>
onApply(
Object.keys(checkedState).filter((key) => checkedState[key]),
)
}
size="sm">
Apply
</Button>
</div>
Expand Down
9 changes: 9 additions & 0 deletions packages/ui/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,12 @@ export function getValidChildren(children: React.ReactNode) {
React.isValidElement(child),
) as React.ReactElement[]
}

export function parseCategory(category: string) {
return category.length < 5
? category.toUpperCase()
: category
.split('-')
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ')
}

0 comments on commit 925624c

Please sign in to comment.