Skip to content

Commit

Permalink
[INJIWEB-257]: injiweb theme customization (#44)
Browse files Browse the repository at this point in the history
Signed-off-by: Vijay <[email protected]>
  • Loading branch information
vijay151096 authored Apr 27, 2024
1 parent a1b97d8 commit d14798c
Show file tree
Hide file tree
Showing 29 changed files with 376 additions and 165 deletions.
28 changes: 17 additions & 11 deletions inji-web/src/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,24 @@ import {Footer} from "./components/PageTemplate/Footer";
import {HelpPage} from "./pages/HelpPage";
import {CredentialsPage} from "./pages/CredentialsPage";
import {RedirectionPage} from "./pages/RedirectionPage";
import {useSelector} from "react-redux";
import {RootState} from "./types/redux";

export const AppRouter = () => {

const theme = useSelector((state: RootState) => state.common.theme);
const wrapElement = (element: JSX.Element) => {
return <React.Fragment>
<div className={`root ${theme}`}>
<Header/>
<div className={"root-body"}>
{element}
</div>
<Footer/>
</div>
</React.Fragment>
}

return (<BrowserRouter>
<Routes>
<Route path="/" element={wrapElement(<HomePage/>)}/>
Expand All @@ -18,14 +34,4 @@ export const AppRouter = () => {
</BrowserRouter>)
}

const wrapElement = (element: JSX.Element) => {
return <React.Fragment>
<div className={"root"}>
<Header/>
<div className={"root-body"}>
{element}
</div>
<Footer/>
</div>
</React.Fragment>
}

3 changes: 2 additions & 1 deletion inji-web/src/components/Common/EmptyListContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ export const EmptyListContainer: React.FC<EmptyListContainerProps> = ({content})
<div data-testid="EmptyList-Outer-Container"
className="flex justify-center items-center w-full mx-auto flex-col h-full">
<div data-testid="EmptyList-Inner-Container" className="container mx-auto mt-8 px-4 flex-1 flex flex-col">
<p data-testid="EmptyList-Text" className="text-center">{content}</p>
<p data-testid="EmptyList-Text"
className="text-center text-light-title dark:text-dark-title">{content}</p>
</div>
</div>
</React.Fragment>
Expand Down
3 changes: 2 additions & 1 deletion inji-web/src/components/Common/HeaderTile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {HeaderTileProps} from "../../types/components";

export const HeaderTile: React.FC<HeaderTileProps> = ({content}) => {
return <React.Fragment>
<div data-testid="HeaderTile-Text" className={"font-bold mt-8 text-xl flex mx-28"}>{content}</div>
<div data-testid="HeaderTile-Text"
className={"font-bold text-light-title dark:text-dark-title mt-8 text-xl flex mx-28"}>{content}</div>
</React.Fragment>
}
6 changes: 4 additions & 2 deletions inji-web/src/components/Common/IntroBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ export const IntroBox: React.FC = () => {
const {t} = useTranslation("HomePage");
return <React.Fragment>
<div data-testid="IntroBox-Container" className="text-center mb-8 pt-20 pb-20">
<h2 data-testid="IntroBox-Text" className="text-2xl font-bold">{t("Intro.title")}</h2>
<p data-testid="IntroBox-SubText" className="text-gray-600 mt-2">{t("Intro.subTitle")}</p>
<h2 data-testid="IntroBox-Text"
className="text-2xl font-bold text-light-title dark:text-dark-title">{t("Intro.title")}</h2>
<p data-testid="IntroBox-SubText"
className="mt-2 text-light-subTitle dark:text-dark-subTitle">{t("Intro.subTitle")}</p>
</div>
</React.Fragment>
}
7 changes: 4 additions & 3 deletions inji-web/src/components/Common/ItemBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ export const ItemBox: React.FC<ItemBoxProps> = (props) => {
return <React.Fragment>
<div key={props.index}
data-testid="ItemBox-Outer-Container"
className="bg-white shadow flex flex-row shadow-blue-100 p-4 rounded-md cursor-pointer items-center"
className="bg-light-background dark:bg-dark-background shadow flex flex-row shadow-light-shadow dark:shadow-dark-shadow p-4 rounded-md cursor-pointer items-center"
onClick={props.onClick}>
<img data-testid="ItemBox-Logo" src={props.url} alt="Issuer Logo"
className="w-30 h-10 justify-center mr-4"/>
<div className={"justify-center items-center"}>
<h3 className="text-lg font-semibold" data-testid="ItemBox-Text">{props.title}</h3>
{props.description && <p>{props.description}</p>}
<h3 className="text-lg font-semibold text-light-title dark:text-dark-title"
data-testid="ItemBox-Text">{props.title}</h3>
{props.description && <p className="text-light-title dark:text-dark-title">{props.description}</p>}
</div>
</div>
</React.Fragment>
Expand Down
16 changes: 8 additions & 8 deletions inji-web/src/components/Common/LanguageSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, {useState} from "react";
import {VscGlobe} from "react-icons/vsc";
import {switchLanguage} from "../../utils/i18n";
import {LanguagesSupported, switchLanguage} from "../../utils/i18n";
import {useDispatch, useSelector} from "react-redux";
import {storeLanguage} from "../../redux/reducers/commonReducer";
import {RootState} from "../../types/redux";
Expand All @@ -22,18 +22,18 @@ export const LanguageSelector: React.FC = () => {
className="relative flex flex-row items-center font-bold bg-white rounded leading-tight">
<VscGlobe
data-testid="Language-Selector-Icon"
size={30} color={"orange"}/>
size={30} color={'orange'}/>
<select
defaultValue={currentLanguage}
id="language"
className={"cursor-pointer"}
className={"cursor-pointer text-light-title dark:text-dark-title"}
data-testid="Language-Selector-Options"
onChange={(event) => handleChange(event.target.value)}>
<option value={"en"}>English</option>
<option value={"ta"}>தமிழ்</option>
<option value={"kn"}>ಕನ್ನಡ</option>
<option value={"hi"}>हिंदी</option>
<option value={"fr"}>Français</option>
{LanguagesSupported.map(lang => {
return <option
className={"text-light-title dark:text-dark-title"}
value={lang.value}>{lang.label}</option>
})}
</select>
</div>
</React.Fragment>
Expand Down
20 changes: 14 additions & 6 deletions inji-web/src/components/Common/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import {IoArrowBack, IoCloseCircleSharp} from "react-icons/io5";
import {FaSearch} from "react-icons/fa";
import {useDispatch} from "react-redux";
import {storeCredentials} from "../../redux/reducers/credentialsReducer";
import {api, MethodType} from "../../utils/api";
import {api} from "../../utils/api";
import {NavBarProps} from "../../types/components";

import {ApiRequest} from "../../types/data";

export const NavBar: React.FC<NavBarProps> = (props) => {

const params = useParams<CredentialParamProps>();
Expand All @@ -18,12 +20,18 @@ export const NavBar: React.FC<NavBarProps> = (props) => {

const filterCredential = async (searchText: string) => {
setSearchText(searchText)
const response = await props.fetchRequest(api.searchCredentialType(params.issuerId, searchText), MethodType.GET, null);
const apiRequest: ApiRequest = api.searchCredentialType;
const response = await props.fetchRequest(
apiRequest.url(params.issuerId, searchText),
apiRequest.methodType,
apiRequest.headers()
);
dispatch(storeCredentials(response?.response?.supportedCredentials))
}

return <React.Fragment>
<div data-testid="NavBar-Outer-Container" className="bg-blue-50 text-black p-4 py-10">
<div data-testid="NavBar-Outer-Container"
className="bg-light-navigationBar dark:bg-dark-navigationBar text-light-title dark:text-dark-title p-4 py-10">
<nav data-testid="NavBar-Inner-Container" className="flex justify-between mx-auto container items-center">
<div className="flex items-center">
<div className={"cursor-pointer"}>
Expand All @@ -38,18 +46,18 @@ export const NavBar: React.FC<NavBarProps> = (props) => {
<div className="relative w-96 mx-auto flex justify-center items-center">
<FaSearch
data-testid="NavBar-Search-Icon"
className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 ml-2"
className="absolute left-3 top-1/2 transform -translate-y-1/2 text-light-searchIcon dark:text-dark-searchIcon ml-2"
size={20}/>
<input
data-testid="NavBar-Search-Input"
type="text"
value={searchText}
placeholder={t("searchText")}
onChange={event => filterCredential(event.target.value)}
className="py-6 pl-16 pr-4 rounded-md w-full shadow-xl focus:outline-none" // Adjusted padding to accommodate the icon
className="py-6 pl-16 pr-4 rounded-md w-full shadow-xl text-light-searchTitle dark:text-dark-searchTitle focus:outline-none" // Adjusted padding to accommodate the icon
/>
{searchText.length > 0 && <IoCloseCircleSharp data-testid="Search-Issuer-Clear-Icon"
className="absolute right-5 top-1/2 transform -translate-y-1/2 text-gray-400 ml-2 cursor-pointer"
className="absolute right-5 top-1/2 transform -translate-y-1/2 text-light-closeIcon dark:text-dark-closeIcon ml-2 cursor-pointer"
onClick={() => filterCredential("")}
size={20}/>}
</div>
Expand Down
31 changes: 31 additions & 0 deletions inji-web/src/components/Common/ThemeMode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from "react";
import {MdDarkMode, MdLightMode} from "react-icons/md";
import {useDispatch, useSelector} from "react-redux";
import {RootState} from "../../types/redux";
import {storeTheme} from "../../redux/reducers/commonReducer";
import {storage} from "../../utils/storage";

export const Theme = {
LIGHT: 'light',
DARK: 'dark'
}
export const ThemeMode: React.FC = () => {
const dispatch = useDispatch();
const theme = useSelector((state: RootState) => state.common.theme);
const handleThemeChange = () => {
const newTheme = theme === Theme.LIGHT ? Theme.DARK : Theme.LIGHT;
dispatch(storeTheme(newTheme));
storage.setItem(storage.SELECTED_THEME, newTheme);
}

return <div onClick={handleThemeChange}>
<div className={"p-2 w-20 h-10 rounded-full border-1 border-2 flex justify-center items-center"}>
<div className={"w-8 h-8 rounded-full flex items-center justify-center"}>
<MdLightMode size={25} color={theme === Theme.DARK ? "" : "orange"}/>
</div>
<div className={"w-8 h-8 rounded-full flex items-center justify-center"}>
<MdDarkMode size={25} color={theme === Theme.DARK ? "blue" : ""}/>
</div>
</div>
</div>
}
13 changes: 8 additions & 5 deletions inji-web/src/components/Help/HelpAccordionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import {IoIosArrowDown, IoIosArrowUp} from "react-icons/io";
export const HelpAccordionItem: React.FC<HelpAccordionItemProps> = (props) => {

return <React.Fragment>
<div className="border rounded-md mb-2 shadow-sm shadow-blue-100" data-testid="Help-Item-Container">
<div className="border rounded-md mb-2 shadow-sm shadow-light-shadow dark:shadow-dark-shadow"
data-testid="Help-Item-Container">
<button
data-testid="Help-Item-Title-Button"
className="w-full p-4 text-left font-bold hover:bg-gray-50 focus:outline-none"
className="w-full p-4 text-left font-bold hover:bg-light-subTitle hover:dark:bg-dark-subTitle focus:outline-none"
onClick={() => props.setOpen(props.id)}
>
<div className={"flex flex-row"} data-testid="Help-Item-Title-Text">
<div className={"flex flex-row text-light-title dark:text-dark-title"}
data-testid="Help-Item-Title-Text">
{props.title}
<div className={"flex items-center ml-auto"}>
{
Expand All @@ -23,8 +25,9 @@ export const HelpAccordionItem: React.FC<HelpAccordionItemProps> = (props) => {
</div>
</button>
{(props.id === props.open) && (
<div className="p-4 bg-white border-t-2" data-testid="Help-Item-Content-Text">
{props.content.map(content => <p>{content}</p>)}
<div className="p-4 bg-light-background dark:bg-dark-background border-t-2"
data-testid="Help-Item-Content-Text">
{props.content.map(content => <p className={"text-light-title dark:text-dark-title"}>{content}</p>)}

</div>
)}
Expand Down
2 changes: 1 addition & 1 deletion inji-web/src/components/Issuers/IssuersList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const IssuersList: React.FC<IssuersListProps> = ({state}) => {

return <React.Fragment>
<div data-testid="Issuers-List-Container"
className="container mx-auto my-auto mt-8 px-4 flex-1 flex flex-col border-2">
className="container mx-auto my-auto mt-8 px-4 flex-1 flex flex-col">
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
{issuers.issuers.map((issuer: IssuerObject, index: number) =>
<Issuer issuer={issuer} index={index}/>)}
Expand Down
18 changes: 12 additions & 6 deletions inji-web/src/components/Issuers/SearchIssuer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import {useTranslation} from "react-i18next";
import {FaSearch} from 'react-icons/fa';
import {useDispatch} from "react-redux";
import {storeIssuers} from "../../redux/reducers/issuersReducer";
import {api, MethodType} from "../../utils/api";
import {IssuerObject} from "../../types/data";
import {api} from "../../utils/api";
import {ApiRequest, IssuerObject} from "../../types/data";
import {IoCloseCircleSharp} from "react-icons/io5";
import {SearchIssuerProps} from "../../types/components";

Expand All @@ -15,25 +15,31 @@ export const SearchIssuer: React.FC<SearchIssuerProps> = (props) => {
const [searchText, setSearchText] = useState("");
const filterIssuers = async (searchText: string) => {
setSearchText(searchText);
const response = await props.fetchRequest(api.searchIssuers(searchText), MethodType.GET, null);
const apiRequest: ApiRequest = api.searchIssuers;
const response = await props.fetchRequest(
apiRequest.url(searchText),
apiRequest.methodType,
apiRequest.headers()
);
dispatch(storeIssuers(response?.response?.issuers.filter((issuer: IssuerObject) => issuer.credential_issuer === 'Sunbird')))
}

return <React.Fragment>
<div data-testid="Search-Issuer-Container" className="mb-8 w-full flex pb-14">
<div className="relative w-3/5 mx-auto flex justify-center items-center">
<FaSearch data-testid="Search-Issuer-Search-Icon"
className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 ml-2" size={20}/>
className="absolute left-3 top-1/2 transform -translate-y-1/2 text-light-searchIcon dark:text-dark-searchIcon ml-2"
size={20}/>
<input
data-testid="Search-Issuer-Input"
type="text"
value={searchText}
placeholder={t("Intro.searchText")}
onChange={event => filterIssuers(event.target.value)}
className="py-6 pl-16 pr-4 rounded-md w-full shadow-xl focus:outline-none"
className="py-6 pl-16 pr-4 rounded-md w-full shadow-md text-light-searchTitle dark:text-dark-searchTitle focus:outline-none"
/>
{searchText.length > 0 && <IoCloseCircleSharp data-testid="Search-Issuer-Clear-Icon"
className="absolute right-5 top-1/2 transform -translate-y-1/2 text-gray-400 ml-2 cursor-pointer"
className="absolute right-5 top-1/2 transform -translate-y-1/2 text-light-closeIcon dark:text-dark-closeIcon ml-2 cursor-pointer"
onClick={() => filterIssuers("")}
size={20}/>}
</div>
Expand Down
2 changes: 1 addition & 1 deletion inji-web/src/components/PageTemplate/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const Footer: React.FC = () => {

return <footer
data-testid="Footer-Container"
className="fixed bottom-0 left-0 right-0 py-4 text-center transform rotate-180 shadow-sm border-blue-10">
className="fixed bottom-0 left-0 right-0 py-4 text-center transform rotate-180 shadow-sm shadow-light-shadow dark:shadow-dark-shadow">
<div className="container mx-auto">
<p data-testid="Footer-Text" className="text-black transform rotate-180">{t("Footer.copyRight")}</p>
</div>
Expand Down
10 changes: 7 additions & 3 deletions inji-web/src/components/PageTemplate/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ import React from "react";
import {useTranslation} from "react-i18next";
import {useNavigate} from "react-router-dom";
import {LanguageSelector} from "../Common/LanguageSelector";
import {ThemeMode} from "../Common/ThemeMode";

export const Header: React.FC = () => {

const {t} = useTranslation("PageTemplate");
const navigate = useNavigate();

return (
<header data-testid="Header-Container" className="fixed top-0 left-0 right-0 bg-white py-4 shadow-sm">
<header data-testid="Header-Container"
className="fixed top-0 left-0 right-0 bg-light-background dark:bg-dark-background py-4 shadow-sm">
<div className="container mx-auto flex justify-between items-center px-4">
<div onClick={() => navigate("/")}>
<img src={require("../../assets/InjiWebLogo.png")}
Expand All @@ -21,14 +23,16 @@ export const Header: React.FC = () => {
<ul className="flex space-x-4 items-center">
<li data-testid="Header-Menu-Help">
<div onClick={() => navigate("/help")}
className="text-black font-bold cursor-pointer">{t("Header.help")}</div>
className="text-light-title dark:text-dark-title font-bold cursor-pointer">{t("Header.help")}</div>
</li>
<li data-testid="Header-Menu-AboutInji"><a href="https://docs.mosip.io/inji" target="_blank"
rel="noreferrer"
className="text-black font-bold">{t("Header.aboutInji")}</a>
className="text-light-title dark:text-dark-title font-bold">{t("Header.aboutInji")}</a>
</li>
<li data-testid="Header-Menu-LanguageSelector"><LanguageSelector/>
</li>
<li data-testid="Header-Menu-ThemeMode"><ThemeMode/>
</li>
</ul>
</nav>
</div>
Expand Down
Loading

0 comments on commit d14798c

Please sign in to comment.