changes to green theme
This commit is contained in:
parent
394d28f80d
commit
0d0b7f2cbc
@ -31,6 +31,8 @@
|
|||||||
<link rel="stylesheet" href="/assets/css/default.css" />
|
<link rel="stylesheet" href="/assets/css/default.css" />
|
||||||
<link rel="stylesheet" href="/assets/css/skeleton.css" />
|
<link rel="stylesheet" href="/assets/css/skeleton.css" />
|
||||||
<link rel="stylesheet" href="/assets/css/hover-utility.css" />
|
<link rel="stylesheet" href="/assets/css/hover-utility.css" />
|
||||||
|
<link rel="stylesheet" href="/assets/css/theme-green.css" />
|
||||||
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="/assets/vendor/libs/perfect-scrollbar/perfect-scrollbar.css" />
|
<link rel="stylesheet" href="/assets/vendor/libs/perfect-scrollbar/perfect-scrollbar.css" />
|
||||||
|
|
||||||
|
|||||||
55
public/assets/css/theme-green.css
Normal file
55
public/assets/css/theme-green.css
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
.btn-green {
|
||||||
|
background-color: #49bf3c;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 50px;
|
||||||
|
padding: 10px 30px;
|
||||||
|
font-weight: 500;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-green-outline {
|
||||||
|
border-color: #49bf3c;
|
||||||
|
background-color: transparent;
|
||||||
|
color: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-green-outline:hover {
|
||||||
|
background-color: #49bf3c;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-square-small {
|
||||||
|
border-radius: 3px;
|
||||||
|
padding-bottom: 5.072px;
|
||||||
|
padding-inline-end: 12px;
|
||||||
|
padding-inline-start: 12px;
|
||||||
|
padding-left: 12px;
|
||||||
|
padding-right: 12px;
|
||||||
|
padding-top: 5.072px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-green:hover {
|
||||||
|
background-color: #00a85a;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-blue {
|
||||||
|
color: #696cff !important;
|
||||||
|
}
|
||||||
|
.text-green {
|
||||||
|
color: #49bf3c !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-outline-green {
|
||||||
|
border-radius: 50px;
|
||||||
|
padding: 10px 30px;
|
||||||
|
font-weight: 500;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-outline-green:hover {
|
||||||
|
background-color: #49bf3c;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
@ -28,16 +28,13 @@
|
|||||||
color: #4fc143;
|
color: #4fc143;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-primary {
|
/* .text-primary {
|
||||||
color: #49bf3c !important;
|
color: #49bf3c !important;
|
||||||
}
|
} */
|
||||||
.text-blue {
|
|
||||||
color: #696cff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary {
|
/* .btn-primary {
|
||||||
background-color: #49bf3c !important;
|
background-color: #49bf3c !important;
|
||||||
}
|
} */
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: "Segoe UI", Roboto, sans-serif;
|
font-family: "Segoe UI", Roboto, sans-serif;
|
||||||
@ -238,28 +235,3 @@ body {
|
|||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
margin-bottom: 25px;
|
margin-bottom: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-green {
|
|
||||||
background-color: #49bf3c;
|
|
||||||
color: #fff;
|
|
||||||
border-radius: 50px;
|
|
||||||
padding: 10px 30px;
|
|
||||||
font-weight: 500;
|
|
||||||
text-decoration: none;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-square-small {
|
|
||||||
border-radius: 3px;
|
|
||||||
padding-bottom: 5.072px;
|
|
||||||
padding-inline-end: 12px;
|
|
||||||
padding-inline-start: 12px;
|
|
||||||
padding-left: 12px;
|
|
||||||
padding-right: 12px;
|
|
||||||
padding-top: 5.072px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-green:hover {
|
|
||||||
background-color: #00a85a;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ const LandingPage = () => {
|
|||||||
<div className="container-fluid px-5 w-100">
|
<div className="container-fluid px-5 w-100">
|
||||||
<div className="row w-100">
|
<div className="row w-100">
|
||||||
<div className="col-md-auto d-flex justify-content-between align-items-center">
|
<div className="col-md-auto d-flex justify-content-between align-items-center">
|
||||||
<a className="navbar-brand fw-bold text-primary" href="#">
|
<a className="navbar-brand fw-bold text-green" href="#">
|
||||||
<span className="text-blue">OnField</span>
|
<span className="text-blue">OnField</span>
|
||||||
<span>Work</span>
|
<span>Work</span>
|
||||||
<span className="text-dark">.com</span>
|
<span className="text-dark">.com</span>
|
||||||
@ -187,7 +187,7 @@ const LandingPage = () => {
|
|||||||
<div className="card-slider p-4 bg-light rounded-4 h-100 text-start border">
|
<div className="card-slider p-4 bg-light rounded-4 h-100 text-start border">
|
||||||
<div className="feature-icon mb-3">
|
<div className="feature-icon mb-3">
|
||||||
<img
|
<img
|
||||||
src="../../../public/img/icons/dashboard.png"
|
src="/img/icons/dashboard.png"
|
||||||
alt="Dashboard"
|
alt="Dashboard"
|
||||||
className="w-14 mb-4 feature-icon-image"
|
className="w-14 mb-4 feature-icon-image"
|
||||||
/>
|
/>
|
||||||
@ -203,7 +203,7 @@ const LandingPage = () => {
|
|||||||
<div className="card-slider p-4 bg-light rounded-4 h-100 text-start border">
|
<div className="card-slider p-4 bg-light rounded-4 h-100 text-start border">
|
||||||
<div className="feature-icon mb-3">
|
<div className="feature-icon mb-3">
|
||||||
<img
|
<img
|
||||||
src="../../../public/img/icons/attendance.png"
|
src="/img/icons/attendance.png"
|
||||||
alt="Smart Attendance"
|
alt="Smart Attendance"
|
||||||
className="w-14 mb-4 feature-icon-image"
|
className="w-14 mb-4 feature-icon-image"
|
||||||
/>
|
/>
|
||||||
@ -220,7 +220,7 @@ const LandingPage = () => {
|
|||||||
<div className="card-slider p-4 bg-light rounded-4 h-100 text-start border">
|
<div className="card-slider p-4 bg-light rounded-4 h-100 text-start border">
|
||||||
<div className="feature-icon mb-3">
|
<div className="feature-icon mb-3">
|
||||||
<img
|
<img
|
||||||
src="../../../public/img/icons/spending.png"
|
src="/img/icons/spending.png"
|
||||||
alt="Expense & Budget Tracking"
|
alt="Expense & Budget Tracking"
|
||||||
className="w-14 mb-4 feature-icon-image"
|
className="w-14 mb-4 feature-icon-image"
|
||||||
/>
|
/>
|
||||||
@ -236,7 +236,7 @@ const LandingPage = () => {
|
|||||||
<div className="card-slider p-4 bg-light rounded-4 h-100 text-start border">
|
<div className="card-slider p-4 bg-light rounded-4 h-100 text-start border">
|
||||||
<div className="feature-icon mb-3">
|
<div className="feature-icon mb-3">
|
||||||
<img
|
<img
|
||||||
src="../../../public/img/icons/directory.png"
|
src="/img/icons/directory.png"
|
||||||
alt="Cloud Scalability"
|
alt="Cloud Scalability"
|
||||||
className="w-14 mb-4 feature-icon-image"
|
className="w-14 mb-4 feature-icon-image"
|
||||||
/>
|
/>
|
||||||
@ -252,7 +252,7 @@ const LandingPage = () => {
|
|||||||
<div className="card-slider p-4 bg-light rounded-4 h-100 text-start border">
|
<div className="card-slider p-4 bg-light rounded-4 h-100 text-start border">
|
||||||
<div className="feature-icon mb-3">
|
<div className="feature-icon mb-3">
|
||||||
<img
|
<img
|
||||||
src="../../../public/img/icons/report.png"
|
src="/img/icons/report.png"
|
||||||
alt="Advanced Reporting"
|
alt="Advanced Reporting"
|
||||||
className="w-14 mb-4 feature-icon-image"
|
className="w-14 mb-4 feature-icon-image"
|
||||||
/>
|
/>
|
||||||
@ -269,7 +269,7 @@ const LandingPage = () => {
|
|||||||
<div className="card-slider p-4 bg-light rounded-4 h-100 text-start border">
|
<div className="card-slider p-4 bg-light rounded-4 h-100 text-start border">
|
||||||
<div className="feature-icon mb-3">
|
<div className="feature-icon mb-3">
|
||||||
<img
|
<img
|
||||||
src="../../../public/img/icons/cloud-service.png"
|
src="/img/icons/cloud-service.png"
|
||||||
alt="Cloud Scalability"
|
alt="Cloud Scalability"
|
||||||
className="w-14 mb-4 feature-icon-image"
|
className="w-14 mb-4 feature-icon-image"
|
||||||
/>
|
/>
|
||||||
@ -298,7 +298,7 @@ const LandingPage = () => {
|
|||||||
<div className="col-md-4">
|
<div className="col-md-4">
|
||||||
<div className="card pricing-card border-0 shadow-sm">
|
<div className="card pricing-card border-0 shadow-sm">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<h5 className="text-primary fw-bold">Starter</h5>
|
<h5 className="text-green fw-bold">Starter</h5>
|
||||||
<h2>
|
<h2>
|
||||||
₹499<span className="fs-6 text-muted">/month</span>
|
₹499<span className="fs-6 text-muted">/month</span>
|
||||||
</h2>
|
</h2>
|
||||||
@ -317,7 +317,7 @@ const LandingPage = () => {
|
|||||||
<div className="col-md-4">
|
<div className="col-md-4">
|
||||||
<div className="card pricing-card border-primary shadow-lg">
|
<div className="card pricing-card border-primary shadow-lg">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<h5 className="text-primary fw-bold">Professional</h5>
|
<h5 className="text-green fw-bold">Professional</h5>
|
||||||
<h2>
|
<h2>
|
||||||
₹999<span className="fs-6 text-muted">/month</span>
|
₹999<span className="fs-6 text-muted">/month</span>
|
||||||
</h2>
|
</h2>
|
||||||
@ -339,7 +339,7 @@ const LandingPage = () => {
|
|||||||
<div className="col-md-4">
|
<div className="col-md-4">
|
||||||
<div className="card pricing-card border-0 shadow-sm">
|
<div className="card pricing-card border-0 shadow-sm">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<h5 className="text-primary fw-bold">Enterprise</h5>
|
<h5 className="text-green fw-bold">Enterprise</h5>
|
||||||
<h2>Custom</h2>
|
<h2>Custom</h2>
|
||||||
<ul className="list-unstyled mt-3 mb-4 text-muted">
|
<ul className="list-unstyled mt-3 mb-4 text-muted">
|
||||||
<li>Dedicated support</li>
|
<li>Dedicated support</li>
|
||||||
@ -360,14 +360,14 @@ const LandingPage = () => {
|
|||||||
<div className="container text-start" style={{ maxWidth: "75%" }}>
|
<div className="container text-start" style={{ maxWidth: "75%" }}>
|
||||||
<h2 className="fw-bold mb-4 text-center">
|
<h2 className="fw-bold mb-4 text-center">
|
||||||
About{" "}
|
About{" "}
|
||||||
<a className="text-primary" href="#">
|
<a className="text-green" href="#">
|
||||||
<span className="text-blue">OnField</span>
|
<span className="text-blue">OnField</span>
|
||||||
<span>Work</span>
|
<span>Work</span>
|
||||||
<span className="text-dark">.com</span>
|
<span className="text-dark">.com</span>
|
||||||
</a>
|
</a>
|
||||||
</h2>
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
<a className="text-primary" href="#">
|
<a className="text-green" href="#">
|
||||||
<span className="text-blue">OnField</span>
|
<span className="text-blue">OnField</span>
|
||||||
<span>Work</span>
|
<span>Work</span>
|
||||||
<span className="text-dark">.com</span>
|
<span className="text-dark">.com</span>
|
||||||
@ -378,7 +378,7 @@ const LandingPage = () => {
|
|||||||
<p>
|
<p>
|
||||||
Whether you manage on-site teams, oversee multiple projects, or
|
Whether you manage on-site teams, oversee multiple projects, or
|
||||||
coordinate vendors and suppliers,{" "}
|
coordinate vendors and suppliers,{" "}
|
||||||
<a className="text-primary" href="#">
|
<a className="text-green" href="#">
|
||||||
<span className="text-blue">OnField</span>
|
<span className="text-blue">OnField</span>
|
||||||
<span>Work</span>
|
<span>Work</span>
|
||||||
<span className="text-dark">.com</span>
|
<span className="text-dark">.com</span>
|
||||||
@ -388,7 +388,7 @@ const LandingPage = () => {
|
|||||||
operations.
|
operations.
|
||||||
</p>
|
</p>
|
||||||
<h5> Our Mission</h5> At{" "}
|
<h5> Our Mission</h5> At{" "}
|
||||||
<a className="text-primary" href="#">
|
<a className="text-green" href="#">
|
||||||
<span className="text-blue">OnField</span>
|
<span className="text-blue">OnField</span>
|
||||||
<span>Work</span>
|
<span>Work</span>
|
||||||
<span className="text-dark">.com</span>
|
<span className="text-dark">.com</span>
|
||||||
@ -401,7 +401,7 @@ const LandingPage = () => {
|
|||||||
a comprehensive suite of tools designed to handle every critical
|
a comprehensive suite of tools designed to handle every critical
|
||||||
aspect of field management — from workforce tracking to expense
|
aspect of field management — from workforce tracking to expense
|
||||||
control and reporting. With
|
control and reporting. With
|
||||||
<a className="text-primary" href="#">
|
<a className="text-green" href="#">
|
||||||
<span className="text-blue">OnField</span>
|
<span className="text-blue">OnField</span>
|
||||||
<span>Work</span>
|
<span>Work</span>
|
||||||
<span className="text-dark">.com</span>
|
<span className="text-dark">.com</span>
|
||||||
@ -443,7 +443,7 @@ const LandingPage = () => {
|
|||||||
</ul>
|
</ul>
|
||||||
<h5>
|
<h5>
|
||||||
Why Choose{" "}
|
Why Choose{" "}
|
||||||
<a className="text-primary" href="#">
|
<a className="text-green" href="#">
|
||||||
<span className="text-blue">OnField</span>
|
<span className="text-blue">OnField</span>
|
||||||
<span>Work</span>
|
<span>Work</span>
|
||||||
<span className="text-dark">.com</span>
|
<span className="text-dark">.com</span>
|
||||||
@ -498,7 +498,7 @@ const LandingPage = () => {
|
|||||||
aria-expanded="true"
|
aria-expanded="true"
|
||||||
aria-controls="accordionOne"
|
aria-controls="accordionOne"
|
||||||
>
|
>
|
||||||
What is MarcoPMS?
|
What is OnFieldWork.com?
|
||||||
</button>
|
</button>
|
||||||
</h2>
|
</h2>
|
||||||
<div
|
<div
|
||||||
@ -552,7 +552,7 @@ const LandingPage = () => {
|
|||||||
aria-expanded="false"
|
aria-expanded="false"
|
||||||
aria-controls="accordionThree"
|
aria-controls="accordionThree"
|
||||||
>
|
>
|
||||||
How secure is Marco PMS?
|
How secure is OnFieldWork.com?
|
||||||
</button>
|
</button>
|
||||||
</h2>
|
</h2>
|
||||||
<div
|
<div
|
||||||
@ -562,14 +562,14 @@ const LandingPage = () => {
|
|||||||
data-bs-parent="#accordionExample"
|
data-bs-parent="#accordionExample"
|
||||||
>
|
>
|
||||||
<div className="accordion-body text-start">
|
<div className="accordion-body text-start">
|
||||||
Security is at the core of Marco PMS. We use industry-standard
|
Security is at the core of OnFieldWork.com. We use
|
||||||
encryption (SSL/TLS) to protect data in transit and advanced
|
industry-standard encryption (SSL/TLS) to protect data in
|
||||||
encryption to safeguard data at rest. Role-based access
|
transit and advanced encryption to safeguard data at rest.
|
||||||
controls ensure that only authorized users can access
|
Role-based access controls ensure that only authorized users
|
||||||
sensitive information. Our system is hosted on secure,
|
can access sensitive information. Our system is hosted on
|
||||||
cloud-ready infrastructure with regular backups, monitoring,
|
secure, cloud-ready infrastructure with regular backups,
|
||||||
and compliance with best practices to keep your data safe and
|
monitoring, and compliance with best practices to keep your
|
||||||
available at all times.
|
data safe and available at all times.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -621,8 +621,8 @@ const LandingPage = () => {
|
|||||||
data-bs-parent="#accordionExample"
|
data-bs-parent="#accordionExample"
|
||||||
>
|
>
|
||||||
<div className="accordion-body text-start">
|
<div className="accordion-body text-start">
|
||||||
Marco PMS operate under a proprietary license combined with a
|
OnFieldWork.com operate under a proprietary license combined
|
||||||
subscription model. This means customers don’t own the
|
with a subscription model. This means customers don’t own the
|
||||||
software but are granted the right to access and use it
|
software but are granted the right to access and use it
|
||||||
through the cloud under our Terms of Service. Depending on the
|
through the cloud under our Terms of Service. Depending on the
|
||||||
plan, licensing may be based on users, features, or usage, and
|
plan, licensing may be based on users, features, or usage, and
|
||||||
@ -640,7 +640,7 @@ const LandingPage = () => {
|
|||||||
aria-expanded="false"
|
aria-expanded="false"
|
||||||
aria-controls="accordionSix"
|
aria-controls="accordionSix"
|
||||||
>
|
>
|
||||||
Can I customize Marco PMS for my business needs?
|
Can I customize OnFieldWork.com for my business needs?
|
||||||
</button>
|
</button>
|
||||||
</h2>
|
</h2>
|
||||||
<div
|
<div
|
||||||
@ -650,8 +650,8 @@ const LandingPage = () => {
|
|||||||
data-bs-parent="#accordionExample"
|
data-bs-parent="#accordionExample"
|
||||||
>
|
>
|
||||||
<div className="accordion-body text-start">
|
<div className="accordion-body text-start">
|
||||||
Yes, Marco PMS is designed to be flexible and adaptable. You
|
Yes, OnFieldWork.com is designed to be flexible and adaptable.
|
||||||
can customize workflows, user roles, permissions, and
|
You can customize workflows, user roles, permissions, and
|
||||||
reporting to match your organization’s unique processes.
|
reporting to match your organization’s unique processes.
|
||||||
Depending on your plan, we also support advanced customization
|
Depending on your plan, we also support advanced customization
|
||||||
such as integrating with third-party tools, adding custom
|
such as integrating with third-party tools, adding custom
|
||||||
@ -680,7 +680,7 @@ const LandingPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="col-lg-6 contact-text">
|
<div className="col-lg-6 contact-text">
|
||||||
<h2>
|
<h2>
|
||||||
Contact <span className="text-success">Us</span>
|
Contact <span className="text-green">Us</span>
|
||||||
</h2>
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
We’d love to hear from you! Whether you have a question about
|
We’d love to hear from you! Whether you have a question about
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { AuthWrapper } from "./AuthWrapper"
|
import { AuthWrapper } from "./AuthWrapper";
|
||||||
import "./page-auth.css";
|
import "./page-auth.css";
|
||||||
import AuthRepository from "../../repositories/AuthRepository";
|
import AuthRepository from "../../repositories/AuthRepository";
|
||||||
import showToast from "../../services/toastService";
|
import showToast from "../../services/toastService";
|
||||||
@ -8,54 +8,65 @@ import { useForm } from "react-hook-form";
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
|
|
||||||
const forgotPassSceham = z.object({
|
const forgotPassSceham = z.object({
|
||||||
email: z.string().trim().email(),
|
email: z.string().trim().email(),
|
||||||
})
|
});
|
||||||
|
|
||||||
const ForgotPasswordPage = () => {
|
const ForgotPasswordPage = () => {
|
||||||
|
const [loding, setLoading] = useState(false);
|
||||||
|
|
||||||
const [loding, setLoading] = useState(false)
|
const {
|
||||||
|
register,
|
||||||
const { register,
|
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
formState: { errors },
|
formState: { errors },
|
||||||
reset,
|
reset,
|
||||||
getValues } = useForm({
|
getValues,
|
||||||
resolver: zodResolver(forgotPassSceham),
|
} = useForm({
|
||||||
defaultValues: {
|
resolver: zodResolver(forgotPassSceham),
|
||||||
email: ""
|
defaultValues: {
|
||||||
}
|
email: "",
|
||||||
})
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const onSubmit = async (data) => {
|
const onSubmit = async (data) => {
|
||||||
try {
|
try {
|
||||||
setLoading(true)
|
setLoading(true);
|
||||||
const response = await AuthRepository.forgotPassword(data)
|
const response = await AuthRepository.forgotPassword(data);
|
||||||
if (response.data && response.success)
|
if (response.data && response.success)
|
||||||
showToast("verification email has been sent to your registered email address", "success")
|
showToast(
|
||||||
reset()
|
"verification email has been sent to your registered email address",
|
||||||
setLoading(false)
|
"success"
|
||||||
|
);
|
||||||
|
reset();
|
||||||
|
setLoading(false);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
reset()
|
reset();
|
||||||
if (err.response.status === 404) {
|
if (err.response.status === 404) {
|
||||||
showToast("verification email has been sent to your registered email address", "success")
|
showToast(
|
||||||
|
"verification email has been sent to your registered email address",
|
||||||
|
"success"
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
showToast("Something wrong", "error")
|
showToast("Something wrong", "error");
|
||||||
}
|
}
|
||||||
|
|
||||||
setLoading(false)
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
return (
|
return (
|
||||||
<div className="col-12 col-lg-5 col-xl-4 d-flex align-items-center p-4 p-sm-5 bg-gray-60">
|
<div className="col-12 col-lg-5 col-xl-4 d-flex align-items-center p-4 p-sm-5 bg-gray-60">
|
||||||
<div className="w-100" style={{ maxWidth: 420, margin: "0 auto" }}>
|
<div className="w-100" style={{ maxWidth: 420, margin: "0 auto" }}>
|
||||||
<h4 className="mb-2">Forgot Password? 🔒</h4>
|
<h4 className="mb-2">Forgot Password? 🔒</h4>
|
||||||
<p className="mb-4">
|
<p className="mb-4">
|
||||||
Enter your email and we'll send you instructions to reset your password
|
Enter your email and we'll send you instructions to reset your
|
||||||
|
password
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<form id="formAuthentication" className="mb-3" onSubmit={handleSubmit(onSubmit)}>
|
<form
|
||||||
|
id="formAuthentication"
|
||||||
|
className="mb-3"
|
||||||
|
onSubmit={handleSubmit(onSubmit)}
|
||||||
|
>
|
||||||
<div className="mb-3 text-start">
|
<div className="mb-3 text-start">
|
||||||
<label htmlFor="email" className="form-label">
|
<label htmlFor="email" className="form-label">
|
||||||
Email
|
Email
|
||||||
@ -78,23 +89,22 @@ const ForgotPasswordPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<button aria-label="Click me" className="btn btn-primary d-grid w-100">
|
<button aria-label="Click me" className=" btn-green d-grid w-100">
|
||||||
{loding ? "Please Wait..." : "Send Reset Link"}
|
{loding ? "Please Wait..." : "Send Reset Link"}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<Link
|
<Link
|
||||||
aria-label="Go to Login Page"
|
aria-label="Go to Login Page"
|
||||||
to="/auth/login"
|
to="/auth/login"
|
||||||
className="d-flex align-items-center justify-content-center"
|
className="d-flex align-items-center justify-content-center text-green"
|
||||||
>
|
>
|
||||||
<i className="bx bx-chevron-left scaleX-n1-rtl bx-sm"></i>
|
<i className="bx bx-chevron-left scaleX-n1-rtl bx-sm text-green"></i>
|
||||||
Back to login
|
Back to login
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Footer Text */}
|
{/* Footer Text */}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -49,16 +49,16 @@ const LoginPage = () => {
|
|||||||
// sessionStorage.setItem("refreshToken", response.data.refreshToken);
|
// sessionStorage.setItem("refreshToken", response.data.refreshToken);
|
||||||
// }
|
// }
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
localStorage.setItem("jwtToken", response.data.token);
|
localStorage.setItem("jwtToken", response.data.token);
|
||||||
localStorage.setItem("refreshToken", response.data.refreshToken);
|
localStorage.setItem("refreshToken", response.data.refreshToken);
|
||||||
navigate("/dashboard",{ replace: true });
|
navigate("/dashboard", { replace: true });
|
||||||
} else {
|
} else {
|
||||||
await AuthRepository.sendOTP({ email: data.username });
|
await AuthRepository.sendOTP({ email: data.username });
|
||||||
showToast("OTP has been sent to your email.", "success");
|
showToast("OTP has been sent to your email.", "success");
|
||||||
localStorage.setItem("otpUsername", data.username);
|
localStorage.setItem("otpUsername", data.username);
|
||||||
localStorage.setItem("otpSentTime", now.toString());
|
localStorage.setItem("otpSentTime", now.toString());
|
||||||
// navigate("/auth/login-otp");
|
// navigate("/auth/login-otp");
|
||||||
navigate("/dashboard",{ replace: true });
|
navigate("/dashboard", { replace: true });
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showToast("Invalid username or password.", "error");
|
showToast("Invalid username or password.", "error");
|
||||||
@ -78,14 +78,13 @@ const LoginPage = () => {
|
|||||||
}, [IsLoginWithOTP]);
|
}, [IsLoginWithOTP]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const token =
|
const token =
|
||||||
localStorage.getItem("jwtToken") ||
|
localStorage.getItem("jwtToken") || sessionStorage.getItem("jwtToken");
|
||||||
sessionStorage.getItem("jwtToken");
|
|
||||||
|
|
||||||
if (token) {
|
if (token) {
|
||||||
navigate("/dashboard", { replace: true });
|
navigate("/dashboard", { replace: true });
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="col-12 col-lg-5 col-xl-4 d-flex align-items-center p-4 p-sm-5 bg-gray-60">
|
<div className="col-12 col-lg-5 col-xl-4 d-flex align-items-center p-4 p-sm-5 bg-gray-60">
|
||||||
@ -182,7 +181,7 @@ const LoginPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
<Link
|
<Link
|
||||||
to="/auth/forgot-password"
|
to="/auth/forgot-password"
|
||||||
className="text-decoration-none"
|
className="text-decoration-none text-green"
|
||||||
>
|
>
|
||||||
Forgot Password?
|
Forgot Password?
|
||||||
</Link>
|
</Link>
|
||||||
@ -191,11 +190,7 @@ const LoginPage = () => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Submit */}
|
{/* Submit */}
|
||||||
<button
|
<button type="submit" className=" btn-green w-100" disabled={loading}>
|
||||||
type="submit"
|
|
||||||
className="btn btn-primary w-100"
|
|
||||||
disabled={loading}
|
|
||||||
>
|
|
||||||
{loading
|
{loading
|
||||||
? "Please Wait..."
|
? "Please Wait..."
|
||||||
: IsLoginWithOTP
|
: IsLoginWithOTP
|
||||||
@ -211,7 +206,7 @@ const LoginPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-outline-secondary w-100"
|
className="btn-green btn-green-outline w-100"
|
||||||
onClick={() => setLoginWithOtp(true)}
|
onClick={() => setLoginWithOtp(true)}
|
||||||
>
|
>
|
||||||
Login With OTP
|
Login With OTP
|
||||||
@ -224,17 +219,20 @@ const LoginPage = () => {
|
|||||||
{!IsLoginWithOTP ? (
|
{!IsLoginWithOTP ? (
|
||||||
<p className="text-center mt-3">
|
<p className="text-center mt-3">
|
||||||
<span>New on our platform? </span>
|
<span>New on our platform? </span>
|
||||||
<Link to="/auth/reqest/demo" className="btn btn-link p-0">
|
<Link
|
||||||
|
to="/auth/reqest/demo"
|
||||||
|
className="btn btn-link p-0 text-green"
|
||||||
|
>
|
||||||
Request a Demo
|
Request a Demo
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
) : (
|
) : (
|
||||||
<div className="text-center mt-3">
|
<div className="text-center mt-3">
|
||||||
<button
|
<button
|
||||||
className="btn btn-link p-0"
|
className="btn btn-link p-0 text-green"
|
||||||
onClick={() => setLoginWithOtp(false)}
|
onClick={() => setLoginWithOtp(false)}
|
||||||
>
|
>
|
||||||
<i className="bx bx-chevron-left scaleX-n1-rtl bx-sm"></i>
|
<i className="bx bx-chevron-left scaleX-n1-rtl bx-sm "></i>
|
||||||
Back to login
|
Back to login
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -21,7 +21,6 @@ const LoginWithOtp = () => {
|
|||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [timeLeft, setTimeLeft] = useState(0);
|
const [timeLeft, setTimeLeft] = useState(0);
|
||||||
|
|
||||||
|
|
||||||
const inputRefs = useRef([]);
|
const inputRefs = useRef([]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -43,17 +42,16 @@ const LoginWithOtp = () => {
|
|||||||
try {
|
try {
|
||||||
let requestedData = {
|
let requestedData = {
|
||||||
email: username,
|
email: username,
|
||||||
otp: finalOtp
|
otp: finalOtp,
|
||||||
}
|
};
|
||||||
const response = await AuthRepository.verifyOTP(requestedData)
|
const response = await AuthRepository.verifyOTP(requestedData);
|
||||||
|
|
||||||
localStorage.setItem("jwtToken", response.data.token);
|
localStorage.setItem("jwtToken", response.data.token);
|
||||||
localStorage.setItem("refreshToken", response.data.refreshToken);
|
localStorage.setItem("refreshToken", response.data.refreshToken);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
localStorage.removeItem("otpUsername");
|
localStorage.removeItem("otpUsername");
|
||||||
localStorage.removeItem("otpSentTime");
|
localStorage.removeItem("otpSentTime");
|
||||||
navigate("/auth/switch/org");
|
navigate("/auth/switch/org");
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showToast("Invalid or expired OTP.", "error");
|
showToast("Invalid or expired OTP.", "error");
|
||||||
|
|
||||||
@ -61,7 +59,9 @@ const LoginWithOtp = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const formatTime = (seconds) => {
|
const formatTime = (seconds) => {
|
||||||
const min = Math.floor(seconds / 60).toString().padStart(2, "0");
|
const min = Math.floor(seconds / 60)
|
||||||
|
.toString()
|
||||||
|
.padStart(2, "0");
|
||||||
const sec = (seconds % 60).toString().padStart(2, "0");
|
const sec = (seconds % 60).toString().padStart(2, "0");
|
||||||
return `${min}:${sec}`;
|
return `${min}:${sec}`;
|
||||||
};
|
};
|
||||||
@ -78,7 +78,6 @@ const LoginWithOtp = () => {
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (timeLeft <= 0) return;
|
if (timeLeft <= 0) return;
|
||||||
|
|
||||||
@ -112,22 +111,22 @@ const LoginWithOtp = () => {
|
|||||||
}
|
}
|
||||||
trigger(["otp1", "otp2", "otp3", "otp4"]);
|
trigger(["otp1", "otp2", "otp3", "otp4"]);
|
||||||
} else {
|
} else {
|
||||||
showToast("Invalid OTP format pasted. Please enter 4 digits")
|
showToast("Invalid OTP format pasted. Please enter 4 digits");
|
||||||
|
|
||||||
for (let i = 0; i < 4; i++) {
|
for (let i = 0; i < 4; i++) {
|
||||||
setValue(`otp${i + 1}`, "")
|
setValue(`otp${i + 1}`, "");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// <AuthWrapper>
|
// <AuthWrapper>
|
||||||
<div className="col-12 col-lg-5 col-xl-4 d-flex align-items-center justify-content-center p-4 p-sm-5 bg-gray-60 h-100">
|
<div className="col-12 col-lg-5 col-xl-4 d-flex align-items-center justify-content-center p-4 p-sm-5 bg-gray-60 h-100">
|
||||||
<div className="block p-4 p-sm-5 bg-gray-60">
|
<div className="block p-4 p-sm-5 bg-gray-60">
|
||||||
<h4>Verify Your OTP</h4>
|
<h4>Verify Your OTP</h4>
|
||||||
<p className="mb-4">Please enter the 4-digit code sent to your email.</p>
|
<p className="mb-4">
|
||||||
|
Please enter the 4-digit code sent to your email.
|
||||||
|
</p>
|
||||||
|
|
||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<div className="d-flex justify-content-center gap-6 mb-3">
|
<div className="d-flex justify-content-center gap-6 mb-3">
|
||||||
@ -139,8 +138,9 @@ const LoginWithOtp = () => {
|
|||||||
key={num}
|
key={num}
|
||||||
type="text"
|
type="text"
|
||||||
maxLength={1}
|
maxLength={1}
|
||||||
className={`form-control text-center ${errors[`otp${num}`] ? "is-invalid" : ""
|
className={`form-control text-center ${
|
||||||
}`}
|
errors[`otp${num}`] ? "is-invalid" : ""
|
||||||
|
}`}
|
||||||
ref={(el) => {
|
ref={(el) => {
|
||||||
inputRefs.current[idx] = el;
|
inputRefs.current[idx] = el;
|
||||||
ref(el);
|
ref(el);
|
||||||
@ -150,7 +150,6 @@ const LoginWithOtp = () => {
|
|||||||
onChange(e);
|
onChange(e);
|
||||||
if (/^\d$/.test(val) && idx < 3) {
|
if (/^\d$/.test(val) && idx < 3) {
|
||||||
inputRefs.current[idx + 1]?.focus();
|
inputRefs.current[idx + 1]?.focus();
|
||||||
|
|
||||||
} else if (val === "" && idx > 0) {
|
} else if (val === "" && idx > 0) {
|
||||||
inputRefs.current[idx - 1]?.focus();
|
inputRefs.current[idx - 1]?.focus();
|
||||||
}
|
}
|
||||||
@ -164,7 +163,6 @@ const LoginWithOtp = () => {
|
|||||||
inputRefs.current[idx - 1]?.focus();
|
inputRefs.current[idx - 1]?.focus();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
onPaste={idx === 0 ? handlePaste : undefined}
|
onPaste={idx === 0 ? handlePaste : undefined}
|
||||||
style={{ width: "40px", height: "40px", fontSize: "15px" }}
|
style={{ width: "40px", height: "40px", fontSize: "15px" }}
|
||||||
{...rest}
|
{...rest}
|
||||||
@ -184,7 +182,7 @@ const LoginWithOtp = () => {
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="btn btn-primary d-grid w-100"
|
className="btn-green d-grid w-100"
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
>
|
>
|
||||||
{loading ? "Verifying..." : "Verify OTP"}
|
{loading ? "Verifying..." : "Verify OTP"}
|
||||||
@ -199,19 +197,20 @@ const LoginWithOtp = () => {
|
|||||||
</p>
|
</p>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
<p
|
<p className="text-center text-danger mt-2 text small-text m-0">
|
||||||
className="text-center text-danger mt-2 text small-text m-0"
|
|
||||||
|
|
||||||
>
|
|
||||||
OTP has expired. Please request a new one.
|
OTP has expired. Please request a new one.
|
||||||
</p>
|
</p>
|
||||||
<a className="text-primary cursor-pointer" onClick={() => navigate('/auth/login')}>Try Again</a>
|
<a
|
||||||
|
className="text-green cursor-pointer"
|
||||||
|
onClick={() => navigate("/auth/login")}
|
||||||
|
>
|
||||||
|
Try Again
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
)}
|
)}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
// </AuthWrapper>
|
// </AuthWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user