Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Established Initial UI Structure and Components of E-Truck pass #355

Merged
merged 5 commits into from
Mar 5, 2025
Merged
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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mock-relying-party-ui/public/images/close_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mock-relying-party-ui/public/images/globe_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mock-relying-party-ui/public/images/ideal_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mock-relying-party-ui/public/images/mail_id_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mock-relying-party-ui/public/images/retry_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mock-relying-party-ui/public/images/tick_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mock-relying-party-ui/public/images/trash_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mock-relying-party-ui/public/images/upload_cloud.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
35 changes: 23 additions & 12 deletions mock-relying-party-ui/src/App.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
import "./App.css";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import LoginPage from "./pages/Login";
import UserProfilePage from "./pages/UserProfile";
import SignUpPage from "./pages/SignUp";
import RegistrationPage from "./pages/Registration";
import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom";
import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import { useTranslation } from "react-i18next";
import { useEffect, useState } from "react";
import langConfigService from "./services/langConfigService";
import Login from './travelPass/pages/auth/Login';
import MainLayout from "./travelPass/pages/MainLayout";
import Dashboard from "./travelPass/components/Dashboard";
import ApplyForTravelPass from "./travelPass/components/ApplyForTravelPass";
import CreateTravelMain from "./travelPass/components/createETravelPass/CreateTravelMain";


import LoginPage from "./pages/Login";
import UserProfilePage from "./pages/UserProfile";
import SignUpPage from "./pages/SignUp";
import RegistrationPage from "./pages/Registration";
import BookAppointmentPage from "./pages/BookAppointment";
import UploadEinvoicePage from "./travelPass/components/createETravelPass/UploadEinvoicePage";
import PreviewDetails from "./travelPass/components/createETravelPass/PreviewDetails";
import CongratulationsPopup from "./travelPass/components/createETravelPass/CongratulationsPopup";

function App() {
const { i18n } = useTranslation();
const [langOptions, setLangOptions] = useState([]);
const [dir, setDir] = useState("ltr");
const [isTravelPass, setIsTravelPass] = useState(false);

//Loading rtlLangs
useEffect(() => {
Expand Down Expand Up @@ -47,18 +58,18 @@ function App() {
}, []);

return (
<div dir={dir} className="h-screen">
<div dir={dir} className="h-full">
<BrowserRouter>
<Routes>
<Route path={process.env.PUBLIC_URL + "/"} element={<LoginPage langOptions={langOptions} />} />
<Route path={process.env.PUBLIC_URL + "/signup"} element={<SignUpPage langOptions={langOptions} />} />
<Route path={process.env.PUBLIC_URL + "/userprofile"} element={<UserProfilePage langOptions={langOptions} />} />
<Route path={process.env.PUBLIC_URL + "/registration"} element={<RegistrationPage langOptions={langOptions} />} />
<Route path={process.env.PUBLIC_URL + "/bookappointment"} element={<BookAppointmentPage langOptions={langOptions}/>}/>
<Route path="/" element={<Navigate to={process.env.PUBLIC_URL + "/login"} replace />} />
<Route path={process.env.PUBLIC_URL + "/login"} element={<MainLayout> <Login /> </MainLayout>} />
<Route path={process.env.PUBLIC_URL + "/dashboard"} element={<MainLayout> <Dashboard /> </MainLayout>} />
<Route path={process.env.PUBLIC_URL + "/applyForTravelPass"} element={<MainLayout> <ApplyForTravelPass /> </MainLayout>} />
<Route path={process.env.PUBLIC_URL + "/userprofile"} element={<MainLayout> <CreateTravelMain /> </MainLayout>} />
</Routes>
</BrowserRouter>
<ToastContainer position="top-center" hideProgressBar={true} pauseOnHover={false} draggable={false} />
</div>
</div >
);
}

Expand Down
1 change: 1 addition & 0 deletions mock-relying-party-ui/src/services/relyingPartyService.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const post_fetchUserInfo = async (
});
return response.data;
};

const get_claimProvider = () => {
return {
claimproviders: [
Expand Down
11 changes: 11 additions & 0 deletions mock-relying-party-ui/src/travelPass/Main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'
import './i18n/i18n.jsx'

createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>,
)
26 changes: 26 additions & 0 deletions mock-relying-party-ui/src/travelPass/appUtils/UseOutsideClick.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useEffect } from 'react';

/**
* A custom hook to detect clicks outside of a specified element.
* @param {object} ref - A React ref for the element to detect outside clicks for.
* @param {function} callback - A function to call when an outside click is detected.
*/
const useOutsideClick = (ref, callback) => {
useEffect(() => {
const handleClickOutside = (event) => {
if (ref.current && !ref.current.contains(event.target)) {
callback(); // Call the callback when a click outside is detected
}
};

// Add event listener
document.addEventListener('mousedown', handleClickOutside);

// Cleanup event listener on unmount
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [ref, callback]);
};

export default useOutsideClick;
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import clientDetails from '../../constants/clientDetails';
import { useExternalScript } from "../../hooks/useExternalScript";


function ApplyForTravelPass() {
const navigate = useNavigate();
const signInButtonScript = window._env_.SIGN_IN_BUTTON_PLUGIN_URL;
const state = useExternalScript(signInButtonScript);

useEffect(() => {
renderSignInButton();
}, [state])

const renderSignInButton = () => {

const oidcConfig = {
authorizeUri: clientDetails.uibaseUrl + clientDetails.authorizeEndpoint,
redirect_uri: clientDetails.redirect_uri_userprofile,
client_id: clientDetails.clientId,
scope: clientDetails.scopeUserProfile,
nonce: clientDetails.nonce,
state: clientDetails.state,
acr_values: clientDetails.acr_values,
claims_locales: clientDetails.claims_locales,
display: clientDetails.display,
prompt: clientDetails.prompt,
max_age: clientDetails.max_age,
ui_locales: 'en',
claims: JSON.parse(decodeURIComponent(clientDetails.userProfileClaims)),
};

window.SignInWithEsignetButton?.init({
oidcConfig: oidcConfig,
buttonConfig: {
shape: "soft_edges",
labelText: 'Sign In with eSignet',
width: "100%"
},
signInElement: document.getElementById("sign-in-with-esignet"),
});
}

return (
<div className='flex justify-center bg-[#F9F5FF] font-inter'>
<div className='flex flex-col absolute mt-[1.1rem] gap-y-3'>
<h2 className='font-semibold text-[2rem] text-[#42307D] place-self-center'>
Apply For TravelPass
</h2>
<img scr='images/left_band_2.png' />
<div className='flex bg-white h-[28.6rem] w-[58.5rem] justify-between border items-center px-[1.8rem] mb-[1rem] rounded-xl shadow'>
<img src='images/online_account_profile_icon.png' className='h-[15.25rem] mt-[1rem]' />
<div className='flex-col flex justify-between w-[21rem] h-[21rem] text-[#514A6A]'>
<h4 className='text-md font-base'>The Travel Pass Portal enables company representatives to apply for travel passes to cross borders</h4>
<p className='text-sm font-base'>Follow this simple process:</p>
<ol className='place-self-start space-y-3'>
<li className='flex gap-x-1 text-xs font-normal text-[#514A6A]'>
<p className='border-[0.1rem] border-[#7F56D9] rounded-[2rem] w-[1.1rem] h-[1.1rem] px-[0.24rem] text-[#7F56D9]'>1</p>
s <p className='text-md font-base'>Enter Traveller/Driver National ID</p>
</li>
<li className='flex gap-x-1 text-xs font-normal text-[#514A6A]'>
<p className='border-[0.1rem] border-[#7F56D9] rounded-[2rem] w-[1.1rem] h-[1.1rem] px-[0.24rem] text-[#7F56D9]'>2</p>
<p className='text-md font-base'>Verify National ID</p>
</li>
<li className='flex gap-x-1 text-xs font-normal text-[#514A6A]'>
<p className='border-[0.1rem] border-[#7F56D9] rounded-[2rem] w-[1.1rem] h-[1.1rem] px-[0.24rem] text-[#7F56D9]'>3</p>
<p className='text-md font-base'>Upload E-Invoice</p>
</li>
<li className='flex gap-x-1 text-xs font-normal text-[#514A6A]'>
<p className='border-[0.1rem] border-[#7F56D9] rounded-[2rem] w-[1.1rem] h-[1.1rem] px-[0.24rem] text-[#7F56D9]'>4</p>
<p className='text-md font-base'>Travel Pass VC available for download from Inji Wallet</p>
</li>
</ol>
{/* <button className={`bg-purple-600 hover:bg-[#7F56D9] cursor-pointer w-[20rem] text-xs text-white py-2 mt-3 shadow-sm rounded-md`} onClick={fetchDetails}>
Enter Traveller National ID
</button> */}
<div id="sign-in-with-esignet" className="w-full"></div>
</div>
</div>
</div>
<img src='images/background_pattern.png' className='h-[38rem] w-full' />
</div>
)
}

export default ApplyForTravelPass;
23 changes: 23 additions & 0 deletions mock-relying-party-ui/src/travelPass/components/Dashboard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@


function Dashboard() {
return (
<div className="h-[37rem] flex flex-col items-center py-8 relative overflow-hidden bg-[rgba(249,245,255,1)]">
<div>
<div className="absolute top-[65%] left-[-6%] w-[24%] min-[1800px]:w-[40%] h-24 bg-[rgba(233,215,254,1)] transform -rotate-10"></div>
<div className="absolute top-[75%] left-[-5%] w-[24%] min-[1800px]:w-[40%] h-14 bg-[rgba(214,187,251,1)] transform -rotate-10"></div>
</div>

<div>
<div className="absolute top-[35%] left-[54%] w-[56%] h-24 bg-[rgba(214,187,251,1)] transform -rotate-10"></div>
<div className="absolute top-[45%] left-[54%] w-[56%] h-14 bg-[rgba(233,215,254,1)] transform -rotate-10"></div>
</div>

<div className="absolute top-[76%] left-[-10%] w-[120%] h-[50%] bg-white transform -rotate-10 z-0"></div>


</div>
);
}

export default Dashboard;
52 changes: 52 additions & 0 deletions mock-relying-party-ui/src/travelPass/components/DashboardOne.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { useNavigate } from "react-router-dom";

function DashboardWithoutDetails () {

return (
<>
<div className="text-center mb-10 relative z-5">
<span className="bg-[rgba(249,245,255,1)] text-[rgba(105,65,198,1)] px-3 py-1 rounded-full text-sm border border-[#E9D7FE]">Text</span>
<h1 className="text-5xl font-semibold text-[rgba(66,48,125,1)] mt-6">Apply for Digi-Pass</h1>
<p className="text-[rgba(105,65,198,1)] mt-6 max-w-xl mx-auto">
Lorem ipsum dolor sit amet consectetur. Pulvinar non nisi nunc ac nullam nam.
</p>
</div>

<div className="flex gap-6 max-w-6xl relative z-10 mt-8">
{/* Card 1 */}
<div className="bg-white shadow-lg rounded-2xl p-8 text-center flex flex-col items-center w-[592px] h-[292px] border border-gray-200">
<div className="bg-purple-100 p-4 mb-4 w-16 h-16 flex items-center justify-center rounded-lg">
<span className="text-purple-600 text-3xl"></span>
</div>
<h2 className="text-lg font-semibold text-purple-800">
For Users with Digital National ID
</h2>
<p className="text-gray-500 mt-2 text-sm">Online process</p>
<div className="border-t border-gray-200 w-full mt-4 pt-4">
<button className="bg-[rgba(127,86,217,1)] text-white py-3 px-6 rounded-lg w-full hover:bg-purple-700">
Verify National ID
</button>
</div>
</div>

{/* Card 2 */}
<div className="bg-white shadow-lg rounded-2xl p-8 text-center flex flex-col items-center w-[592px] h-[292px] border border-gray-200">
<div className="bg-purple-100 p-4 mb-4 w-16 h-16 flex items-center justify-center rounded-lg">
<span className="text-purple-600 text-3xl">📄</span>
</div>
<h2 className="text-lg font-semibold text-purple-800">
For Users without Digital ID
</h2>
<p className="text-gray-500 mt-2 text-sm">Upload Documents</p>
<div className="border-t border-gray-200 w-full mt-4 pt-4">
<button className="bg-[rgba(127,86,217,1)] text-white py-3 px-6 rounded-lg w-full hover:bg-purple-700">
Get started
</button>
</div>
</div>
</div>
</>
);
}

export default DashboardWithoutDetails;
9 changes: 9 additions & 0 deletions mock-relying-party-ui/src/travelPass/components/Input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export default function Input({ type = "text", className, ...props }) {
return (
<input
type={type}
className={`${className}`}
{...props}
/>
);
}
48 changes: 48 additions & 0 deletions mock-relying-party-ui/src/travelPass/components/Stepper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { useEffect, useState } from "react";

export default function Stepper({ uploadStatus, previewStatus, moveBack }) {
const [uploaded, setUploaded] = useState(true);
const [previewed, setPreviewed] = useState(false);

useEffect(() => {
if (uploadStatus) {
setUploaded(false);
setPreviewed(false);
}
if (previewStatus) {
setPreviewed(true);
}
if (moveBack) {
setUploaded(true);
setPreviewed(false);
}
}, [uploadStatus, previewStatus, moveBack]);

let steps = [
{ id: "verifyTravellerId", title: "Verify Traveller National ID", description: "Lorem ipsum dolor sit amet consectetur", isActive: false, processCompleted: true, },
{ id: "uploadEInvoice", title: "Upload E-Invoice", description: "Lorem ipsum dolor sit amet consectetur dolor sit", isActive: uploaded, processCompleted: !uploaded },
{ id: "previewDetails", title: "Preview Details", description: "Lorem ipsum dolor sit amet consectetur", isActive: !uploaded, processCompleted: previewed },
{ id: "passIssued", title: "Travel Pass Issued", description: "Lorem ipsum dolor sit amet consecteturdolor sit", isActive: previewed, processCompleted: false }
];

return (
<ol className="flex items-center justify-center">
{steps.map((eachStep, index) => {
return (
<li key={index} id={eachStep.id} className={`${(index + 1) < steps.length ? 'w-[24%]' : ''} mt-[4%]`}>
<div className={`flex w-full items-center after:content-[''] after:w-full after:h-1 ${(index + 1) < steps.length ? (eachStep.processCompleted ? 'after:border-b after:border-[#966af3] after:border-4' : 'after:border-b after:border-[#ededee] after:border-4') : ''} after:inline-block`}>
{eachStep.processCompleted
? <img src='images/tick_icon.png' />
: (eachStep.isActive ? <img src='images/activeStep_icon.png' className="h-6" /> : <img src='images/ideal_icon.png' />)
}
</div>
<div className="flex justify-center flex-col absolute w-[400px] text-center -ml-[185px] text-sm mt-2">
<p className={`font-semibold text-[#6941C6] ${eachStep.isActive ? 'text-[#6941C6]' : 'text-[#344054]'}`}>{eachStep.title}</p>
<p className={`${eachStep.isActive ? 'text-[#7F56D9]' : 'text-[#475467]'}`}>{eachStep.description}</p>
</div>
</li>
)
})}
</ol>
)
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react';

function CongratulationsPopup() {
return (
<div className='bg-white h-full border border-[#E4E7EC] rounded-lg shadow-sm'>
<div className='flex flex-col h-[22rem] py-[1rem] items-center justify-center space-y-3 text-center'>
<img
src='images/congratulations.gif'
alt='Congratulation_gif'
className='h-[10rem] w-[10rem]'
/>
<h1 className='text-2xl font-bold text-[#42307D]'>Congratulations!</h1>
<p className='text-lg font-semibold text-[#42307D]'>Your driver's travel pass is now ready for download</p>
<p className='text-sm font-[500] text-[#42307D] w-[25rem]'>Please ask your driver/traveler to download the travel pass and keep it accessible for smooth border crossing.</p>
<div className='flex justify-around w-[25rem] mb-[2rem]'>
<button className='border border-[#a08ae9] hover:bg-[#7F56D9] hover:text-white text-sm text-[#42307D] rounded-md px-7 py-2'>Inji Mobile Wallet</button>
<button className='border border-[#a08ae9] text-sm text-[#42307D] hover:bg-[#7F56D9] hover:text-white rounded-md px-7 py-2'>Inji Web Wallet</button>
</div>
</div>
</div>
)
}

export default CongratulationsPopup;
Loading