This commit is contained in:
Sean Edmunds
2025-04-15 20:21:25 -05:00
parent 2e72b76e95
commit 78dec160b6
34 changed files with 225 additions and 466 deletions

View File

@@ -12,16 +12,21 @@ import { useCommonHooks, useMutationAPI, useQueryAPI } from 'hooks';
import { useEffect, useState } from 'react';
import { FiEdit, FiTrash } from 'react-icons/fi';
import { actionIconClasses, selectClasses } from 'styles';
import type { Application, Provider } from 'types';
import type { Application, CurrentWeather, ExtendedForecast, Provider } from 'types';
export default function Search({
current,
outlook,
extendedForecast,
weatherModalOpened,
closeWeatherModal,
openWeatherModal,
}: any) {
}: {
current: CurrentWeather;
extendedForecast: ExtendedForecast[];
weatherModalOpened: boolean;
closeWeatherModal: () => void;
openWeatherModal: () => void;
}) {
const { data: providers, isFetched: providersIsFetched } = useQueryAPI({
endpoint: 'api/providers',
});
@@ -29,14 +34,13 @@ export default function Search({
const { data: apps, isFetching: isAppsFetching } = useQueryAPI({
endpoint: 'api/apps',
});
const [applicationData, setApplicationData] = useState<any>([]);
const [applicationData, setApplicationData] = useState<Application[]>([]);
const { data: history, isFetched: historyIsFetched } = useQueryAPI({
endpoint: 'api/searchHistory',
});
const [searchHistory, setSearchHistory] = useState<any>([]);
const [filteredHistory, setFilteredHistory] = useState<any>([]);
const { mutateAsync: createHistoryItem } = useMutationAPI();
const { mutateAsync: deleteHistoryItem } = useMutationAPI();
const { mutateAsync } = useMutationAPI();
const [providerModalOpened, { open: openProviderModal, close: closeProviderModal }] =
useDisclosure(false);
const [dropdownOpened, { open: openDropdown, close: closeDropdown }] = useDisclosure();
@@ -59,7 +63,7 @@ export default function Search({
const handleSearchHistoryItem = (item: any) => {
const url =
providers.find((provider: any) => provider.prefix === item.option.prefix)?.url ||
providers.find((provider: any) => provider.prefix === item.option.prefix)?.url ??
'https://www.google.com/search?q=';
open(`${url}${item.option.searchTerm}`, '_self');
};
@@ -73,7 +77,7 @@ export default function Search({
let subtext = '';
if (item.target.value.startsWith('/')) {
option =
item.target.value.substr(1, item.target.value.indexOf(' ') - 1) ||
item.target.value.substr(1, item.target.value.indexOf(' ') - 1) ??
item.target.value.substr(1);
subtext = item.target.value.substr(2 + option.length);
} else if (item.target.value.startsWith('!')) {
@@ -87,7 +91,7 @@ export default function Search({
if (providerLabel === 'Show help') {
openProviderModal();
} else if (item.target.value.startsWith('/')) {
createHistoryItem({
mutateAsync({
method: 'POST',
endpoint: 'api/searchHistory',
body: { prefix: providerPrefix, provider: providerLabel, searchTerm: subtext },
@@ -100,16 +104,18 @@ export default function Search({
const url = applicationData.find(
(app: Application) =>
app.baseUrl.substring(1).toLowerCase() === item.target.value.substr(1),
).url;
)?.url;
const validUrl =
url.startsWith('http://') || url.startsWith('https://') ? url : `http://${url}`;
url?.startsWith('http://') || url?.startsWith('https://')
? url
: `http://${url}`;
open(validUrl, '_self');
} else if (urlPattern.test(item.target.value)) {
if (/^(https?:\/\/).*/i.test(item.target.value))
window.location = item.target.value;
else open(`https://${item.target.value}`, '_self');
} else {
createHistoryItem({
mutateAsync({
method: 'POST',
endpoint: 'api/searchHistory',
body: { prefix: providerPrefix, provider: providerLabel, searchTerm: subtext },
@@ -220,8 +226,8 @@ export default function Search({
setProviderLabel('Show weather');
} else if (
applicationData?.find(
(app: any) =>
app.baseUrl.substr(1).toLowerCase() === item.target.value.substr(1),
(app: Application) =>
app.baseUrl.substring(1).toLowerCase() === item.target.value.substr(1),
)
) {
setProviderLabel(`Launch ${item.target.value.substr(1)}`);
@@ -239,10 +245,10 @@ export default function Search({
const splittedSearch = search.toLowerCase().trim().split(' ');
if (splittedSearch[0].startsWith('!')) {
return apps
.filter((app: any) =>
.filter((app: Application) =>
app.name.toLowerCase().includes(splittedSearch[0].substring(1).toLowerCase()),
)
.map((app: any) => {
.map((app: Application) => {
return {
label: app.name,
value: app.baseUrl,
@@ -257,7 +263,7 @@ export default function Search({
.toLowerCase()
.trim()
.split(' ')
.some((word: any) => word.includes(searchWord)),
.some((word: string) => word.includes(searchWord)),
);
})
.slice(0, 10);
@@ -327,7 +333,7 @@ export default function Search({
classNames={actionIconClasses}
onClick={(e) => {
e.stopPropagation();
deleteHistoryItem({
mutateAsync({
method: 'DELETE',
endpoint: 'api/searchHistory',
body: { id: item.option.id },
@@ -417,7 +423,7 @@ export default function Search({
const option = `${item.prefix} ${item.searchTerm}`;
const words = option.toLowerCase().trim().split(' ');
return splittedSearch.every((searchWord) =>
words.some((word: any) => word.includes(searchWord)),
words.some((word: string) => word.includes(searchWord)),
);
})
.slice(0, 10);
@@ -482,20 +488,19 @@ export default function Search({
setSearchValue={setSearchValue}
setProviderLabel={setProviderLabel}
setProviderURL={setProviderURL}
providerModalOpened={providerModalOpened}
applicationData={applicationData}
providerData={providerData}
providerModalOpened={providerModalOpened}
closeProviderModal={closeProviderModal}
/>
<WeatherModal
current={current}
extendedForecast={extendedForecast}
weatherModalOpened={weatherModalOpened}
setSearchValue={setSearchValue}
setProviderLabel={setProviderLabel}
setProviderURL={setProviderURL}
current={current}
outlook={outlook}
extendedForecast={extendedForecast}
closeWeatherModal={closeWeatherModal}
weatherModalOpened={weatherModalOpened}
/>
</Stack>
);