|
| 1 | +import { SearchResult, searchTable } from '@/app/utils/fts_helpers'; |
| 2 | +import { Autocomplete, Box, Card, CardContent, FormControl, Paper, TextField, Typography } from '@mui/material'; |
| 3 | +import React from 'react'; |
| 4 | +import { useNavigate } from 'react-router-dom'; |
| 5 | +import { TODO_LISTS_ROUTE } from '@/app/router'; |
| 6 | +import { usePowerSync, usePowerSyncQuery } from '@journeyapps/powersync-react'; |
| 7 | +import { LISTS_TABLE, ListRecord } from '@/library/powersync/AppSchema'; |
| 8 | +import { todo } from 'node:test'; |
| 9 | + |
| 10 | +// This is a simple search bar widget that allows users to search for lists and todo items |
| 11 | +export const SearchBarWidget: React.FC<any> = (props) => { |
| 12 | + const [searchResults, setSearchResults] = React.useState<SearchResult[]>([]); |
| 13 | + const [value, setValue] = React.useState<SearchResult | null>(null); |
| 14 | + |
| 15 | + const navigate = useNavigate(); |
| 16 | + const powersync = usePowerSync(); |
| 17 | + |
| 18 | + const handleInputChange = async (value: string) => { |
| 19 | + if (value.length !== 0) { |
| 20 | + let listsSearchResults: any[] = []; |
| 21 | + let todoItemsSearchResults = await searchTable(value, 'todos'); |
| 22 | + for (let i = 0; i < todoItemsSearchResults.length; i++) { |
| 23 | + let res = await powersync.get<ListRecord>(`SELECT * FROM ${LISTS_TABLE} WHERE id = ?`, [ |
| 24 | + todoItemsSearchResults[i]['list_id'] |
| 25 | + ]); |
| 26 | + todoItemsSearchResults[i]['list_name'] = res.name; |
| 27 | + } |
| 28 | + if (!todoItemsSearchResults.length) { |
| 29 | + listsSearchResults = await searchTable(value, 'lists'); |
| 30 | + } |
| 31 | + let formattedListResults: SearchResult[] = listsSearchResults.map( |
| 32 | + (result) => new SearchResult(result['id'], result['name']) |
| 33 | + ); |
| 34 | + let formattedTodoItemsResults: SearchResult[] = todoItemsSearchResults.map((result) => { |
| 35 | + return new SearchResult(result['list_id'], result['list_name'] ?? '', result['description']); |
| 36 | + }); |
| 37 | + setSearchResults([...formattedTodoItemsResults, ...formattedListResults]); |
| 38 | + } |
| 39 | + }; |
| 40 | + |
| 41 | + return ( |
| 42 | + <div> |
| 43 | + <FormControl sx={{ my: 1, display: 'flex' }}> |
| 44 | + <Autocomplete |
| 45 | + freeSolo |
| 46 | + id="autocomplete-search" |
| 47 | + options={searchResults} |
| 48 | + value={value?.id} |
| 49 | + getOptionLabel={(option) => { |
| 50 | + if (option instanceof SearchResult) { |
| 51 | + return option.todoName ?? option.listName; |
| 52 | + } |
| 53 | + return option; |
| 54 | + }} |
| 55 | + renderOption={(props, option) => ( |
| 56 | + <Box component="li" {...props}> |
| 57 | + <Card variant="outlined" sx={{ display: 'flex', width: '100%' }}> |
| 58 | + <CardContent> |
| 59 | + {option.listName && ( |
| 60 | + <Typography sx={{ fontSize: 18 }} color="text.primary" gutterBottom> |
| 61 | + {option.listName} |
| 62 | + </Typography> |
| 63 | + )} |
| 64 | + {option.todoName && ( |
| 65 | + <Typography sx={{ fontSize: 14 }} color="text.secondary"> |
| 66 | + {'\u2022'} {option.todoName} |
| 67 | + </Typography> |
| 68 | + )} |
| 69 | + </CardContent> |
| 70 | + </Card> |
| 71 | + </Box> |
| 72 | + )} |
| 73 | + filterOptions={(x) => x} |
| 74 | + onInputChange={(event, newInputValue, reason) => { |
| 75 | + if (reason === 'clear') { |
| 76 | + setValue(null); |
| 77 | + setSearchResults([]); |
| 78 | + return; |
| 79 | + } |
| 80 | + handleInputChange(newInputValue); |
| 81 | + }} |
| 82 | + onChange={(event, newValue, reason) => { |
| 83 | + if (reason === 'selectOption') { |
| 84 | + if (newValue instanceof SearchResult) { |
| 85 | + navigate(TODO_LISTS_ROUTE + '/' + newValue.id); |
| 86 | + } |
| 87 | + } |
| 88 | + }} |
| 89 | + selectOnFocus |
| 90 | + clearOnBlur |
| 91 | + handleHomeEndKeys |
| 92 | + renderInput={(params) => ( |
| 93 | + <TextField |
| 94 | + {...params} |
| 95 | + label="Search..." |
| 96 | + InputProps={{ |
| 97 | + ...params.InputProps |
| 98 | + }} |
| 99 | + /> |
| 100 | + )} |
| 101 | + /> |
| 102 | + </FormControl> |
| 103 | + </div> |
| 104 | + ); |
| 105 | +}; |
0 commit comments