Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion src/components/HomePage/ResultsSection/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,22 @@ interface ResultsSectionProps {
medicines: Array<{ matching_name: string }>;
selectedMedicine: string;
setSelectedMedicine: (value: string) => void;
dropdownLabel?: string;
}

const ResultsSection: FC<ResultsSectionProps> = ({
medicines,
selectedMedicine,
setSelectedMedicine,
dropdownLabel = "Select Medicine",
}) => {
return (
<div className="p-5" data-testid="results-section">
<div className="m-2 text-lg font-semibold text-center font-inter">
Results
</div>
<Dropdown
label="Select Medicine"
label={dropdownLabel}
options={medicines.map((medicine) => medicine.matching_name)}
onChange={setSelectedMedicine}
value={selectedMedicine}
Expand Down
10 changes: 7 additions & 3 deletions src/components/HomePage/SearchSection/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ interface SearchSectionProps {
setSourceLanguage: (value: string) => void;
handleSearch: () => void;
languages: string[];
searchError: string | null;
setSearchError: (msg: string | null) => void;
searchError: string | null;
loading: boolean;
searchTitle?: string;
searchPlaceholder?: string;
}

const SearchSection: FC<SearchSectionProps> = ({
Expand All @@ -25,6 +27,8 @@ const SearchSection: FC<SearchSectionProps> = ({
setSearchError,
searchError,
loading,
searchTitle = "Search for drug name...",
searchPlaceholder = "Word to search",
}) => {
const [invalidChars, setInvalidChars] = useState<string | null>(null);

Expand Down Expand Up @@ -52,7 +56,7 @@ const SearchSection: FC<SearchSectionProps> = ({
return (
<div className="p-5">
<div className="m-2 text-lg font-semibold text-center font-inter">
Search for drug name...
{searchTitle}
</div>
<div className="flex flex-col gap-5 md:flex-row md:items-center">
<Dropdown
Expand All @@ -65,7 +69,7 @@ const SearchSection: FC<SearchSectionProps> = ({
<input
type="text"
className="w-full md:w-1/2 h-12 text-base font-inter font-semibold text-[#044677] text-center shadow-md border border-gray-300 rounded-md focus:border-[#2f876e] focus:ring-[#2f876e] focus:outline-none p-2"
placeholder="Word to search"
placeholder={searchPlaceholder}
value={inputSearch}
onChange={(e) => setInputSearch(e.target.value)}
data-testid="search-input"
Expand Down
11 changes: 3 additions & 8 deletions src/components/HomePage/TranslateSection/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ interface TranslateSectionProps {
translateError: string | null;
setTranslateError: (msg: string | null) => void;
loading: boolean;
translateTitle?: string;
}

const TranslateSection: FC<TranslateSectionProps> = ({
Expand All @@ -28,6 +29,7 @@ const TranslateSection: FC<TranslateSectionProps> = ({
translateError,
setTranslateError,
loading,
translateTitle = "Translate/Localize drug name...",
}) => {
const [isWarningModalOpen, setIsWarningModalOpen] = useState<boolean>(false);
const [lastResortLoading, setLastResortLoading] = useState<boolean>(false);
Expand Down Expand Up @@ -76,7 +78,7 @@ const TranslateSection: FC<TranslateSectionProps> = ({
className="m-2 text-lg font-semibold text-center font-inter"
data-testid="translate-title"
>
Translate/Localize drug name...
{translateTitle}
</div>
<div
className="flex flex-col gap-5 md:flex-row md:items-center"
Expand Down Expand Up @@ -129,13 +131,6 @@ const TranslateSection: FC<TranslateSectionProps> = ({
data-testid="translate-error"
/>
</div>
{isWarningModalOpen && (
<LastResortWarnModal
onConfirm={handleConfirmEnable}
onCancel={() => setIsWarningModalOpen(false)}
data-testid="last-resort-modal"
/>
)}
</div>
);
};
Expand Down
131 changes: 108 additions & 23 deletions src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import ResultsSection from "@/components/HomePage/ResultsSection";
import TranslateSection from "@/components/HomePage/TranslateSection";
import handleSearch from "@/utils/handleSearch";
import handleTranslate from "@/utils/handleTranslate";
import handleSymptomsSearch from "@/utils/handleSymptomsSearch";
import handleSymptomsTranslate from "@/utils/handleSymptomsTranslate";
import HelpModal from "@/components/ui/modals/HelpModal";
import Head from "next/head";

const NEXT_PUBLIC_API_URL: string | undefined = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8080' ;
const NEXT_PUBLIC_API_URL: string | undefined = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8080';

const languages = ["English", "Ukrainian", "Russian", "French"];

Expand All @@ -26,40 +28,75 @@ const HomePage: FC = () => {
}>>(
[],
);
const [symptoms, setSymptoms] = useState<Array<{
matching_algorithm: string,
matching_name: string,
matching_row_number: number,
matching_source: number,
matching_uid: number,
}>>(
[],
);
const [selectedMedicine, setSelectedMedicine] = useState<string>("");
const [selectedSymptom, setSelectedSymptom] = useState<string>("");
const [targetLanguage, setTargetLanguage] = useState<string>("");
const [sourceLanguage, setSourceLanguage] = useState<string>("");
const [searchError, setSearchError] = useState<string | null>(null);
const [translateError, setTranslateError] = useState<string | null>(null);
const [loadingSearch, setLoadingSearch] = useState<boolean>(false);
const [loadingTranslate, setLoadingTranslate] = useState<boolean>(false);
const [infoSet, setInfoSet] = useState<'medicine' | 'symptoms'>('medicine');

const handleSearchAction = async () => {
setLoadingSearch(true);
await handleSearch(
inputSearch,
sourceLanguage,
setMedicines,
NEXT_PUBLIC_API_URL,
setSearchError,
);
if (infoSet === 'medicine') {
await handleSearch(
inputSearch,
sourceLanguage,
setMedicines,
NEXT_PUBLIC_API_URL,
setSearchError,
);
} else {
await handleSymptomsSearch(
inputSearch,
sourceLanguage,
setSymptoms,
NEXT_PUBLIC_API_URL,
setSearchError,
);
}
setLoadingSearch(false);
};

const handleTranslateAction = async (): Promise<string | null> => {
setLoadingTranslate(true);
try {
const selectedMedicineObject = medicines.find(med => med.matching_name === selectedMedicine);
if (!selectedMedicineObject) {
setTranslateError("Selected medicine not found in the results.");
return null;
if (infoSet === 'medicine') {
const selectedMedicineObject = medicines.find(med => med.matching_name === selectedMedicine);
if (!selectedMedicineObject) {
setTranslateError("Selected medicine not found in the results.");
return null;
}
return await handleTranslate(
selectedMedicineObject,
targetLanguage,
setOutputTranslation,
NEXT_PUBLIC_API_URL,
);
} else {
const selectedSymptomObject = symptoms.find(sym => sym.matching_name === selectedSymptom);
if (!selectedSymptomObject) {
setTranslateError("Selected symptom not found in the results.");
return null;
}
return await handleSymptomsTranslate(
selectedSymptomObject,
targetLanguage,
setOutputTranslation,
NEXT_PUBLIC_API_URL,
);
}
return await handleTranslate(
selectedMedicineObject,
targetLanguage,
setOutputTranslation,
NEXT_PUBLIC_API_URL,
);
} catch (error) {
console.error("Translation error:", error);
setTranslateError("Translation failed.");
Expand All @@ -72,7 +109,20 @@ const HomePage: FC = () => {
const handleSetSourceLanguage = (lang: string) => {
setSourceLanguage(lang);
setSelectedMedicine("");
setSelectedSymptom("");
setOutputTranslation("");
};

const handleInfoSetChange = (newInfoSet: 'medicine' | 'symptoms') => {
setInfoSet(newInfoSet);
setInputSearch("");
setOutputTranslation("");
setSelectedMedicine("");
setSelectedSymptom("");
setMedicines([]);
setSymptoms([]);
setSearchError(null);
setTranslateError(null);
};

const targetLanguages = languages.filter((lang) => lang !== sourceLanguage);
Expand All @@ -81,12 +131,16 @@ const HomePage: FC = () => {
setTargetLanguage("");
setOutputTranslation("");
setTranslateError(null);
}, [selectedMedicine]);
}, [selectedMedicine, selectedSymptom]);

useEffect(() => {
setOutputTranslation("");
}, [targetLanguage]);

const currentResults = infoSet === 'medicine' ? medicines : symptoms;
const currentSelected = infoSet === 'medicine' ? selectedMedicine : selectedSymptom;
const setCurrentSelected = infoSet === 'medicine' ? setSelectedMedicine : setSelectedSymptom;

return (
<div className="relative flex flex-col overflow-hidden">
<Head>
Expand All @@ -112,6 +166,33 @@ const HomePage: FC = () => {

<div className="w-11/12 mx-auto mt-5 border-b-2 md:w-9/12"></div>

{/* Choose Info Set Section */}
<div className="p-5">
<div className="mb-4">
<h3 className="text-lg font-semibold mb-3">Choose Info Set</h3>
<div className="flex gap-6">
<label className="flex items-center gap-2 cursor-pointer">
<input
type="checkbox"
checked={infoSet === 'medicine'}
onChange={() => handleInfoSetChange('medicine')}
className="w-4 h-4"
/>
<span>Medicine/Drug</span>
</label>
<label className="flex items-center gap-2 cursor-pointer">
<input
type="checkbox"
checked={infoSet === 'symptoms'}
onChange={() => handleInfoSetChange('symptoms')}
className="w-4 h-4"
/>
<span>Symptoms</span>
</label>
</div>
</div>
</div>

<SearchSection
inputSearch={inputSearch}
setInputSearch={setInputSearch}
Expand All @@ -122,16 +203,19 @@ const HomePage: FC = () => {
searchError={searchError}
setSearchError={setSearchError}
loading={loadingSearch}
searchTitle={infoSet === 'medicine' ? "Search for drug name..." : "Search for symptoms..."}
searchPlaceholder={infoSet === 'medicine' ? "Word to search" : "Symptom to search"}
/>

<ResultsSection
medicines={medicines}
selectedMedicine={selectedMedicine}
setSelectedMedicine={setSelectedMedicine}
medicines={currentResults}
selectedMedicine={currentSelected}
setSelectedMedicine={setCurrentSelected}
dropdownLabel={infoSet === 'medicine' ? "Select Medicine" : "Select Symptom"}
/>

<TranslateSection
selectedMedicine={selectedMedicine}
selectedMedicine={currentSelected}
targetLanguage={targetLanguage}
setTargetLanguage={setTargetLanguage}
outputTranslation={outputTranslation}
Expand All @@ -141,6 +225,7 @@ const HomePage: FC = () => {
translateError={translateError}
setTranslateError={setTranslateError}
loading={loadingTranslate}
translateTitle={infoSet === 'medicine' ? "Translate/Localize drug name..." : "Translate/Localize symptoms..."}
/>
</div>
</div>
Expand Down
60 changes: 60 additions & 0 deletions src/utils/handleSymptomsSearch/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
const handleSymptomsSearch = async (
inputSearch: string,
sourceLanguage: string,
setSymptoms: (data: Array<{
matching_algorithm: string,
matching_name: string,
matching_row_number: number,
matching_source: number,
matching_uid: number,
}>) => void,
NEXT_PUBLIC_API_URL: string | undefined,
setSearchError: (msg: string | null) => void,
): Promise<void> => {
const languageMapping: { [key: string]: string } = {
English: "en",
Ukrainian: "uk",
Russian: "ru",
French: "fr",
};
const sourceLanguageCode = languageMapping[sourceLanguage];
if (!sourceLanguageCode) {
setSearchError(`Invalid source language: ${sourceLanguage}`);
return;
}
try {
const requestBody = {
query: inputSearch,
source_language: sourceLanguageCode,
};
console.log("Symptoms search parameters:", requestBody);

const response = await fetch(`${NEXT_PUBLIC_API_URL}/symptoms-search/`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(requestBody),
});
if (!response.ok) {
setSearchError(`HTTP error! Status: ${response.status}`);
return;
}
const data = await response.json();
console.log("Received symptoms data:", data);

if (data.results.length === 0) {
setSearchError("No symptoms found.");
setSymptoms([]);
} else {
setSymptoms(data.results);
setSearchError(null);
}
} catch (error) {
console.error("Symptoms search error:", error);
setSearchError("Symptoms search failed.");
setSymptoms([]);
}
};

export default handleSymptomsSearch;
Loading