Skip to content
Open
Show file tree
Hide file tree
Changes from 67 commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
33c23f3
feat(ui): implement reusable SearchBar component
nancymuyeh Sep 17, 2025
dadff60
feat(ui): implement reusable SearchBar component
nancymuyeh Sep 17, 2025
02fdf91
feat(ui): implement reusable SearchBar component
nancymuyeh Sep 18, 2025
07f3c4a
feat(ui): implement reusable SearchBar component
nancymuyeh Sep 18, 2025
581d387
Merge branch 'main' into 31-design-and-implement-shared-reusable-sear…
nancymuyeh Sep 18, 2025
62a576d
fix(ui): mark SearchBar component prop as read-only
nancymuyeh Sep 18, 2025
0f3de59
Merge branch '31-design-and-implement-shared-reusable-search-bar-comp…
nancymuyeh Sep 18, 2025
d886154
fix(ui): increase test coverage
nancymuyeh Sep 18, 2025
b198f93
Merge branch 'main' into 31-design-and-implement-shared-reusable-sear…
nancymuyeh Sep 18, 2025
190f0b3
fix(ui): increase test coverage
nancymuyeh Sep 18, 2025
a24a3d9
fix(ui): refactor useSearchBar hook with extracted helper functions f…
nancymuyeh Sep 18, 2025
a74f693
fix(ui): refactor useSearchBar hook with extracted helper functions f…
nancymuyeh Sep 18, 2025
390b514
Update packages/ui/src/components/SearchBar/SearchBar.view.tsx
nancymuyeh Sep 18, 2025
7f2e481
fix(ui): refactor useSearchBar component for SonarQube compliance
nancymuyeh Sep 19, 2025
5f5396c
fix(ui): refactor useSearchBar component for SonarQube compliance
nancymuyeh Sep 19, 2025
216d993
fix(ui): refactor SearchBar component for SonarQube compliance
nancymuyeh Sep 19, 2025
e04b8bd
fix(ui): refactor SearchBar component for SonarQube compliance
nancymuyeh Sep 19, 2025
3328a72
chore(ui): merge main
nancymuyeh Sep 19, 2025
89b66c6
fix(ui): refactor SearchBar component for SonarQube compliance
nancymuyeh Sep 19, 2025
1161ec1
fix(ui): refactor SearchBar component with more simplifies functionality
nancymuyeh Sep 19, 2025
cd8acd7
fix(ui): update searchbar variants and styling
nancymuyeh Sep 19, 2025
1e6e858
fix(ui): remove unused dependencies
nancymuyeh Sep 19, 2025
103e6c8
fix(ui): remove unused dependencies
nancymuyeh Sep 22, 2025
0cd4017
fix(ui): update searchbar componenet to use global styling from style…
nancymuyeh Sep 22, 2025
8ba9f4b
Merge branch 'main' into 31-design-and-implement-shared-reusable-sear…
nancymuyeh Sep 22, 2025
e885bf6
fix(ui): fix minor lint issue
nancymuyeh Sep 22, 2025
9d2d22f
fix(ui): merge main
nancymuyeh Sep 22, 2025
632273e
Merge remote-tracking branch 'origin' into 31-design-and-implement-sh…
nancymuyeh Sep 22, 2025
eafd972
Merge branch 'main' into 31-design-and-implement-shared-reusable-sear…
nancymuyeh Sep 22, 2025
0fffcc2
Merge branch '31-design-and-implement-shared-reusable-search-bar-comp…
nancymuyeh Sep 23, 2025
9999bf2
fix(ui): fix minor lint issue
nancymuyeh Sep 23, 2025
f87027b
fix(ui): fix minor lint issue
nancymuyeh Sep 23, 2025
f413440
feat(ui): created basic branch manager pages and views
nancymuyeh Sep 23, 2025
251ef91
chore(ui): updated branch manager pages
yvanhenang Sep 24, 2025
cc118e9
chore(ui): updated branch manager pages
yvanhenang Sep 24, 2025
b752a6f
chore(): added basic view staff list
Koufan-De-King Sep 25, 2025
e021e3d
chore(): card with particular staff information
Koufan-De-King Sep 25, 2025
896008d
chore(): sidebar highlights truly active page
Koufan-De-King Sep 25, 2025
e922f26
chore(): modified dashborad
Koufan-De-King Sep 25, 2025
560833d
chore(): modified staff page
Koufan-De-King Sep 25, 2025
c362d9a
chore(): completed staff page
Koufan-De-King Sep 25, 2025
37daf1a
chore(): improved funds forms
Koufan-De-King Sep 25, 2025
5fae691
chore(): used correct flow for allocating cash to a teller
Koufan-De-King Sep 25, 2025
21e3a58
chore(): showed login page if unauthenticated
Koufan-De-King Sep 25, 2025
41366a3
chore(): fixed ui and added logic to approve pending accounts
Koufan-De-King Sep 26, 2025
fccd4b1
feat(ui): update branch managers project structure
nancymuyeh Sep 29, 2025
fb1b3f7
chore(ui): updated branch manager pages
yvanhenang Sep 30, 2025
49c9c6c
chore(ui): updated branch manager pages
yvanhenang Sep 30, 2025
99d6985
chore(): added teller transaction pages
Koufan-De-King Sep 30, 2025
424334c
chore(): added teller transaction pages
Koufan-De-King Sep 30, 2025
31e5557
fix(ui): cashier settle and allocate pages
nancymuyeh Sep 30, 2025
5ab6de9
chore(): fixed logic of teller and cashier processes
Koufan-De-King Oct 1, 2025
3c80866
fix(ui): stlyle branch manager pages
nancymuyeh Oct 2, 2025
0540416
fix(ui): stlyle branch manager pages
nancymuyeh Oct 2, 2025
537838b
chore(): transferred auth handling to fineract apache proxy
Koufan-De-King Oct 6, 2025
b924244
chore(): added list of transactions to cashier details view
Koufan-De-King Oct 8, 2025
51c7948
chore(): improved logic of frontend pages
Koufan-De-King Oct 9, 2025
73db9c9
chore(): improved logic of frontend pages
Koufan-De-King Oct 9, 2025
7ecac96
chore(): fixed redirection to list page of cashiers
Koufan-De-King Oct 10, 2025
b21c020
chore(): fixed redirection to list page of cashiers--amend
Koufan-De-King Oct 10, 2025
2002212
chore(): fixing type errors
Koufan-De-King Oct 10, 2025
3d10eb0
chore(): fixing type errors
Koufan-De-King Oct 10, 2025
836a13e
chore(): adding buttons to pages
Koufan-De-King Oct 10, 2025
d2e5d93
chore(): adding buttons to pages
Koufan-De-King Oct 10, 2025
190255c
chore(): used services for all api logic
Koufan-De-King Oct 12, 2025
8841801
chore(): improved button ui
Koufan-De-King Oct 12, 2025
3952c89
chore(): improved sidebar and sidelined long description fields in ta…
Koufan-De-King Oct 13, 2025
7a2157f
chore(): added workflow to release image
Koufan-De-King Oct 13, 2025
f7cb130
chore(): changed basepath to conform to nginx
Koufan-De-King Oct 13, 2025
a603fa1
chore(): modified cashier transactions ui
Koufan-De-King Oct 14, 2025
320c3cd
feat(ui): add favicon and application display name
nancymuyeh Oct 14, 2025
761246d
chore(): fixed logic in docker env by removing dependency on local st…
Koufan-De-King Oct 14, 2025
5cb34e8
Merge branch 'create-branch-manager-app' of github.com:ADORSYS-GIS/fi…
Koufan-De-King Oct 14, 2025
a1188a0
chore(): used /branchmanager
Koufan-De-King Oct 14, 2025
546d229
chore(): used dependencies insync with shared package
Koufan-De-King Oct 14, 2025
08a6b32
chore(): used dependencies insync with shared package
Koufan-De-King Oct 14, 2025
fd0008e
chore(): trigger workflow
Koufan-De-King Oct 14, 2025
52ebf3e
feat(ui): fix ui styling
nancymuyeh Oct 15, 2025
09a109c
chore(): changes to title pages and buttons
Koufan-De-King Oct 20, 2025
4238e11
feat(ui): update teller assingment page and pending savings account d…
nancymuyeh Oct 20, 2025
86afd0b
Merge branch 'create-branch-manager-app' of github.com:ADORSYS-GIS/fi…
nancymuyeh Oct 20, 2025
b6c777d
chore(ui): updated branch manager pages
yvanhenang Oct 21, 2025
7a1545a
feat(ui): fix ui styling
nancymuyeh Oct 21, 2025
d6f5a07
feat(ui): fix ui styling
nancymuyeh Oct 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
349 changes: 349 additions & 0 deletions docs/shared-components/searchbar.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,349 @@
# SearchBar Component

A reusable search input component with multiple variants for different use cases.

## Overview

The SearchBar component provides a search input with search icon, optional clear functionality, and loading states. It comes in three variants to handle different UI scenarios.

## Installation

```typescript
import { SearchBar } from "@fineract-apps/ui";
import "@fineract-apps/ui/styles.css";
```

## Variants

### Default
A standard search input with search icon and clear button. Updates the value as you type.

```typescript
function BasicSearch() {
const [searchValue, setSearchValue] = useState("");

return (
<SearchBar
value={searchValue}
onValueChange={setSearchValue}
placeholder="Search transactions..."
/>
);
}
```

### With Button
Adds a "Search" button for explicit search actions. Good for triggered searches rather than real-time filtering.

```typescript
function SearchWithButton() {
const [query, setQuery] = useState("");

const handleSearch = (searchTerm: string) => {
console.log("Searching for:", searchTerm);
// Your search logic here
};

return (
<SearchBar
variant="withButton"
value={query}
onValueChange={setQuery}
onSearch={handleSearch}
placeholder="Search customers..."
/>
);
}
```

### Expandable
Starts as a search icon, expands into a full input when clicked. Useful for mobile layouts or when space is limited.

```typescript
function ExpandableSearch() {
const [searchTerm, setSearchTerm] = useState("");

return (
<SearchBar
variant="expandable"
value={searchTerm}
onValueChange={setSearchTerm}
placeholder="Quick search..."
/>
);
}
```

## Props

The SearchBar is designed to work seamlessly with TanStack Query for backend integration. Use `onValueChange` for real-time filtering of local data, and `onSearch` for triggered API calls when working with server-side search endpoints.

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `value` | `string` | `""` | Current search input value - control this with React state |
| `onValueChange` | `(value: string) => void` | - | Called on every keystroke - use for real-time filtering or updating search state |
| `onSearch` | `(value: string) => void` | - | Called when user presses Enter or clicks search button - use to trigger TanStack Query refetch |
| `placeholder` | `string` | `"Search..."` | Descriptive placeholder text to guide users (e.g., "Search customers by name...") |
| `variant` | `"default" \| "withButton" \| "expandable"` | `"default"` | Choose based on UX: `default` for filtering, `withButton` for explicit searches, `expandable` for mobile |
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | Size of the search input |
| `disabled` | `boolean` | `false` | Whether the input is disabled |
| `isLoading` | `boolean` | `false` | Shows loading spinner when true |
| `showClear` | `boolean` | `true` | Whether to show clear button when there's text |
| `className` | `string` | - | Additional CSS classes |

## Sizes

| Size | Height | Use Case |
|------|--------|----------|
| `sm` | 32px | Compact interfaces, mobile |
| `md` | 40px | Default size for most use cases |
| `lg` | 44px | Prominent search features |

## Common Usage Patterns

### Loading State

Show a spinner while performing async search operations. Use the `isLoading` prop to display loading feedback to users.

```typescript
function SearchWithLoading() {
const [query, setQuery] = useState("");
const [isLoading, setIsLoading] = useState(false);

const handleSearch = async (searchTerm: string) => {
setIsLoading(true);
// Your async search logic
await fetchResults(searchTerm);
setIsLoading(false);
};

return (
<SearchBar
variant="withButton"
value={query}
onValueChange={setQuery}
onSearch={handleSearch}
isLoading={isLoading}
placeholder="Search..."
/>
);
}
```

### Real-time Filtering

Filter a list of items as the user types. The search updates immediately without needing to press Enter or click a button.

```typescript
function FilterableList() {
const [searchTerm, setSearchTerm] = useState("");
const [items] = useState(["Apple", "Banana", "Cherry"]);

const filteredItems = items.filter(item =>
item.toLowerCase().includes(searchTerm.toLowerCase())
);

return (
<div>
<SearchBar
value={searchTerm}
onValueChange={setSearchTerm}
placeholder="Filter items..."
/>

<ul>
{filteredItems.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
);
}
```

## Keyboard Navigation

- **Enter**: Triggers search action
- **Escape**: Clears input and collapses expandable variant
- **Tab**: Focus navigation between elements

## Styling

Add custom styles using the `className` prop:

```typescript
<SearchBar
value={searchValue}
onValueChange={setSearchValue}
className="w-full max-w-md"
size="lg"
/>
```



## Integration with Button Component

### Button Usage Details

The SearchBar internally uses the Button component for all interactive elements:

#### Clear Button (X)
```typescript
// Rendered when showClear={true} and there's input value
<Button
variant="ghost"
size="sm"
className="p-1 h-auto w-auto hover:bg-accent"
aria-label="Clear input"
>
<X className="h-3 w-3" />
</Button>
```

#### Search Button (withButton variant)
```typescript
// Rendered when variant="withButton"
<Button
size="sm"
className="px-3 py-1 text-sm"
onClick={handleSearch}
disabled={disabled}
>
Search
</Button>
```

#### Expandable Trigger Button
```typescript
// Rendered when variant="expandable" and not expanded
<Button
variant="ghost"
size="sm"
className="cursor-pointer justify-center"
aria-label="Open search"
>
<Search className="h-4 w-4 text-muted-foreground" />
</Button>
```

## Testing

The SearchBar component includes comprehensive test coverage (97%+). Here are example test patterns:

```typescript
import { render, screen, fireEvent } from '@testing-library/react';
import { SearchBar } from './SearchBar';

test('handles user input correctly', () => {
const mockOnValueChange = jest.fn();

render(
<SearchBar
value=""
onValueChange={mockOnValueChange}
/>
);

const input = screen.getByRole('textbox');
fireEvent.change(input, { target: { value: 'test query' } });

expect(mockOnValueChange).toHaveBeenCalledWith('test query');
});

test('button interactions work correctly', () => {
const mockOnSearch = jest.fn();

render(
<SearchBar
variant="withButton"
value="test"
onValueChange={() => {}}
onSearch={mockOnSearch}
/>
);

const searchButton = screen.getByRole('button', { name: /search/i });
fireEvent.click(searchButton);

expect(mockOnSearch).toHaveBeenCalledWith('test');
});
```

## Best Practices

### Component Usage
1. **Use appropriate variants**: Choose `expandable` for mobile/compact layouts, `withButton` for explicit search actions, `default` for real-time filtering
2. **Size selection**: Use `sm` for compact interfaces, `md` for standard layouts, `lg` for prominent search features
3. **Provide meaningful placeholders**: Help users understand what they can search for (e.g., "Search customers by name or ID...")

### State Management
4. **Handle empty states**: Show appropriate messages when no results are found
5. **Loading states**: Always use `isLoading` prop during async operations to provide user feedback
6. **Controlled inputs**: Always use controlled pattern with `value` and `onValueChange` for predictable behavior

### Accessibility & UX
7. **Keyboard navigation**: Test Enter key for search, Escape for clearing/closing, Tab for focus management
8. **ARIA labels**: Provide descriptive labels for screen readers
9. **Error handling**: Implement proper validation and error messaging
10. **Performance**: Consider debouncing for expensive search operations (implement in your handler, not in the component)

### Styling & Theme
11. **Consistent theming**: Rely on CSS variables rather than custom classes when possible
12. **Button consistency**: Let the integrated Button component handle all interactive styling
13. **Responsive design**: Use different variants for different screen sizes

## Troubleshooting

### Common Issues

**Input not updating:**
- Ensure you're using controlled input pattern with `value` and `onValueChange`
- Check that `onValueChange` callback is properly implemented
- Verify state updates are not being blocked by parent components

**Search not triggering:**
- Check that `onSearch` callback is properly implemented for `withButton` variant
- Verify Enter key handling works (should trigger automatically)
- Ensure the input has focus when pressing Enter

**Buttons not working:**
- Verify Button component is properly imported in your app
- Check that CSS variables are defined in your theme
- Ensure `@fineract-apps/ui/styles.css` is imported

**Styling issues:**
- Import UI library styles: `import "@fineract-apps/ui/styles.css"`
- Check that CSS variables are properly defined in your theme
- Use `className` prop for additional custom styling
- Verify Tailwind CSS is configured correctly

**Focus/accessibility problems:**
- Test keyboard navigation (Tab, Enter, Escape)
- Verify ARIA labels are working with screen readers
- Check focus-visible states are appearing correctly

**TypeScript errors:**
- Ensure proper prop types are used
- Check that `onValueChange` signature matches `(value: string) => void`
- Verify `onSearch` callback signature matches `(value: string) => void`

### Performance Issues

**Slow search responses:**
- Implement debouncing in your search handler (not in the component)
- Consider using `isLoading` state during async operations
- Avoid heavy operations in `onValueChange` callbacks

### Getting Help

For additional support:
- Check the component tests for comprehensive usage examples
- Review the TypeScript types for complete API documentation
- Consult the architecture guide for integration patterns
- See the Button component docs for styling details
- Check the CSS variables in `styles.css` for theming options

---

*This component is part of the fineract-apps shared UI library. For technical issues or feature requests, please refer to the project's contribution guidelines.*
30 changes: 30 additions & 0 deletions frontend/branchmanager-app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Branch Manager App

This app implements the Branch Manager experience using the shared UI library and TanStack Router.

## Available routes

- `/login` — simple login screen (navigates to dashboard)
- `/dashboard` — main dashboard with alerts, summary cards, tabs, and a filterable approvals table
- `/funds/allocate` — Allocate funds to tellers (Form)
- `/funds/settle` — Settle funds from tellers (Form)
- `/staff/assign` — Manage staff assignments (initial static view)
- `/branches` — Placeholder
- `/reports` — Placeholder
- `/settings` — Placeholder

## Run locally

```sh
pnpm --dir ../../ dev # from monorepo root: pnpm --dir fineract-apps --filter ./frontend/branchmanager-app... dev
# or from this folder
pnpm dev
```

Then open the local URL printed in the terminal (e.g., http://localhost:5173/).

## Notes

- Styles come from `@fineract-apps/ui/styles.css`.
- Routes are file-based in `src/routes` and generated into `routeTree.gen.ts` by the TanStack Router plugin.
- Forms use the shared `Form` and `Input` components for consistent UX.
Loading
Loading