changes to green theme

This commit is contained in:
Vikas Nale 2025-10-23 12:41:58 +05:30
parent 394d28f80d
commit 0d0b7f2cbc
7 changed files with 187 additions and 151 deletions

View File

@ -31,6 +31,8 @@
<link rel="stylesheet" href="/assets/css/default.css" />
<link rel="stylesheet" href="/assets/css/skeleton.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" />

View 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;
}

View File

@ -28,16 +28,13 @@
color: #4fc143;
}
.text-primary {
/* .text-primary {
color: #49bf3c !important;
}
.text-blue {
color: #696cff !important;
}
} */
.btn-primary {
/* .btn-primary {
background-color: #49bf3c !important;
}
} */
body {
font-family: "Segoe UI", Roboto, sans-serif;
@ -238,28 +235,3 @@ body {
margin-top: 15px;
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;
}

View File

@ -14,7 +14,7 @@ const LandingPage = () => {
<div className="container-fluid px-5 w-100">
<div className="row w-100">
<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>Work</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="feature-icon mb-3">
<img
src="../../../public/img/icons/dashboard.png"
src="/img/icons/dashboard.png"
alt="Dashboard"
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="feature-icon mb-3">
<img
src="../../../public/img/icons/attendance.png"
src="/img/icons/attendance.png"
alt="Smart Attendance"
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="feature-icon mb-3">
<img
src="../../../public/img/icons/spending.png"
src="/img/icons/spending.png"
alt="Expense & Budget Tracking"
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="feature-icon mb-3">
<img
src="../../../public/img/icons/directory.png"
src="/img/icons/directory.png"
alt="Cloud Scalability"
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="feature-icon mb-3">
<img
src="../../../public/img/icons/report.png"
src="/img/icons/report.png"
alt="Advanced Reporting"
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="feature-icon mb-3">
<img
src="../../../public/img/icons/cloud-service.png"
src="/img/icons/cloud-service.png"
alt="Cloud Scalability"
className="w-14 mb-4 feature-icon-image"
/>
@ -298,7 +298,7 @@ const LandingPage = () => {
<div className="col-md-4">
<div className="card pricing-card border-0 shadow-sm">
<div className="card-body">
<h5 className="text-primary fw-bold">Starter</h5>
<h5 className="text-green fw-bold">Starter</h5>
<h2>
499<span className="fs-6 text-muted">/month</span>
</h2>
@ -317,7 +317,7 @@ const LandingPage = () => {
<div className="col-md-4">
<div className="card pricing-card border-primary shadow-lg">
<div className="card-body">
<h5 className="text-primary fw-bold">Professional</h5>
<h5 className="text-green fw-bold">Professional</h5>
<h2>
999<span className="fs-6 text-muted">/month</span>
</h2>
@ -339,7 +339,7 @@ const LandingPage = () => {
<div className="col-md-4">
<div className="card pricing-card border-0 shadow-sm">
<div className="card-body">
<h5 className="text-primary fw-bold">Enterprise</h5>
<h5 className="text-green fw-bold">Enterprise</h5>
<h2>Custom</h2>
<ul className="list-unstyled mt-3 mb-4 text-muted">
<li>Dedicated support</li>
@ -360,14 +360,14 @@ const LandingPage = () => {
<div className="container text-start" style={{ maxWidth: "75%" }}>
<h2 className="fw-bold mb-4 text-center">
About{" "}
<a className="text-primary" href="#">
<a className="text-green" href="#">
<span className="text-blue">OnField</span>
<span>Work</span>
<span className="text-dark">.com</span>
</a>
</h2>
<p>
<a className="text-primary" href="#">
<a className="text-green" href="#">
<span className="text-blue">OnField</span>
<span>Work</span>
<span className="text-dark">.com</span>
@ -378,7 +378,7 @@ const LandingPage = () => {
<p>
Whether you manage on-site teams, oversee multiple projects, or
coordinate vendors and suppliers,{" "}
<a className="text-primary" href="#">
<a className="text-green" href="#">
<span className="text-blue">OnField</span>
<span>Work</span>
<span className="text-dark">.com</span>
@ -388,7 +388,7 @@ const LandingPage = () => {
operations.
</p>
<h5> Our Mission</h5> At{" "}
<a className="text-primary" href="#">
<a className="text-green" href="#">
<span className="text-blue">OnField</span>
<span>Work</span>
<span className="text-dark">.com</span>
@ -401,7 +401,7 @@ const LandingPage = () => {
a comprehensive suite of tools designed to handle every critical
aspect of field management from workforce tracking to expense
control and reporting. With
<a className="text-primary" href="#">
<a className="text-green" href="#">
<span className="text-blue">OnField</span>
<span>Work</span>
<span className="text-dark">.com</span>
@ -443,7 +443,7 @@ const LandingPage = () => {
</ul>
<h5>
Why Choose{" "}
<a className="text-primary" href="#">
<a className="text-green" href="#">
<span className="text-blue">OnField</span>
<span>Work</span>
<span className="text-dark">.com</span>
@ -498,7 +498,7 @@ const LandingPage = () => {
aria-expanded="true"
aria-controls="accordionOne"
>
What is MarcoPMS?
What is OnFieldWork.com?
</button>
</h2>
<div
@ -552,7 +552,7 @@ const LandingPage = () => {
aria-expanded="false"
aria-controls="accordionThree"
>
How secure is Marco PMS?
How secure is OnFieldWork.com?
</button>
</h2>
<div
@ -562,14 +562,14 @@ const LandingPage = () => {
data-bs-parent="#accordionExample"
>
<div className="accordion-body text-start">
Security is at the core of Marco PMS. We use industry-standard
encryption (SSL/TLS) to protect data in transit and advanced
encryption to safeguard data at rest. Role-based access
controls ensure that only authorized users can access
sensitive information. Our system is hosted on secure,
cloud-ready infrastructure with regular backups, monitoring,
and compliance with best practices to keep your data safe and
available at all times.
Security is at the core of OnFieldWork.com. We use
industry-standard encryption (SSL/TLS) to protect data in
transit and advanced encryption to safeguard data at rest.
Role-based access controls ensure that only authorized users
can access sensitive information. Our system is hosted on
secure, cloud-ready infrastructure with regular backups,
monitoring, and compliance with best practices to keep your
data safe and available at all times.
</div>
</div>
</div>
@ -621,8 +621,8 @@ const LandingPage = () => {
data-bs-parent="#accordionExample"
>
<div className="accordion-body text-start">
Marco PMS operate under a proprietary license combined with a
subscription model. This means customers dont own the
OnFieldWork.com operate under a proprietary license combined
with a subscription model. This means customers dont own the
software but are granted the right to access and use it
through the cloud under our Terms of Service. Depending on the
plan, licensing may be based on users, features, or usage, and
@ -640,7 +640,7 @@ const LandingPage = () => {
aria-expanded="false"
aria-controls="accordionSix"
>
Can I customize Marco PMS for my business needs?
Can I customize OnFieldWork.com for my business needs?
</button>
</h2>
<div
@ -650,8 +650,8 @@ const LandingPage = () => {
data-bs-parent="#accordionExample"
>
<div className="accordion-body text-start">
Yes, Marco PMS is designed to be flexible and adaptable. You
can customize workflows, user roles, permissions, and
Yes, OnFieldWork.com is designed to be flexible and adaptable.
You can customize workflows, user roles, permissions, and
reporting to match your organizations unique processes.
Depending on your plan, we also support advanced customization
such as integrating with third-party tools, adding custom
@ -680,7 +680,7 @@ const LandingPage = () => {
</div>
<div className="col-lg-6 contact-text">
<h2>
Contact <span className="text-success">Us</span>
Contact <span className="text-green">Us</span>
</h2>
<p>
Wed love to hear from you! Whether you have a question about

View File

@ -1,6 +1,6 @@
import { useState } from "react";
import { Link } from "react-router-dom";
import { AuthWrapper } from "./AuthWrapper"
import { AuthWrapper } from "./AuthWrapper";
import "./page-auth.css";
import AuthRepository from "../../repositories/AuthRepository";
import showToast from "../../services/toastService";
@ -8,54 +8,65 @@ import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
const forgotPassSceham = z.object({
email: z.string().trim().email(),
})
});
const ForgotPasswordPage = () => {
const [loding, setLoading] = useState(false);
const [loding, setLoading] = useState(false)
const { register,
const {
register,
handleSubmit,
formState: { errors },
reset,
getValues } = useForm({
resolver: zodResolver(forgotPassSceham),
defaultValues: {
email: ""
}
})
getValues,
} = useForm({
resolver: zodResolver(forgotPassSceham),
defaultValues: {
email: "",
},
});
const onSubmit = async (data) => {
try {
setLoading(true)
const response = await AuthRepository.forgotPassword(data)
setLoading(true);
const response = await AuthRepository.forgotPassword(data);
if (response.data && response.success)
showToast("verification email has been sent to your registered email address", "success")
reset()
setLoading(false)
showToast(
"verification email has been sent to your registered email address",
"success"
);
reset();
setLoading(false);
} catch (err) {
reset()
reset();
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 {
showToast("Something wrong", "error")
showToast("Something wrong", "error");
}
setLoading(false)
setLoading(false);
}
}
};
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" }}>
<h4 className="mb-2">Forgot Password? 🔒</h4>
<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>
<form id="formAuthentication" className="mb-3" onSubmit={handleSubmit(onSubmit)}>
<form
id="formAuthentication"
className="mb-3"
onSubmit={handleSubmit(onSubmit)}
>
<div className="mb-3 text-start">
<label htmlFor="email" className="form-label">
Email
@ -78,26 +89,25 @@ const ForgotPasswordPage = () => {
</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"}
</button>
</form>
<div className="text-center">
<Link
aria-label="Go to Login Page"
to="/auth/login"
className="d-flex align-items-center justify-content-center"
>
<i className="bx bx-chevron-left scaleX-n1-rtl bx-sm"></i>
Back to login
</Link>
</div>
<div className="text-center">
<Link
aria-label="Go to Login Page"
to="/auth/login"
className="d-flex align-items-center justify-content-center text-green"
>
<i className="bx bx-chevron-left scaleX-n1-rtl bx-sm text-green"></i>
Back to login
</Link>
</div>
{/* Footer Text */}
</div>
</div>
);
};
export default ForgotPasswordPage;
export default ForgotPasswordPage;

View File

@ -49,16 +49,16 @@ const LoginPage = () => {
// sessionStorage.setItem("refreshToken", response.data.refreshToken);
// }
setLoading(false);
localStorage.setItem("jwtToken", response.data.token);
localStorage.setItem("refreshToken", response.data.refreshToken);
navigate("/dashboard",{ replace: true });
localStorage.setItem("jwtToken", response.data.token);
localStorage.setItem("refreshToken", response.data.refreshToken);
navigate("/dashboard", { replace: true });
} else {
await AuthRepository.sendOTP({ email: data.username });
showToast("OTP has been sent to your email.", "success");
localStorage.setItem("otpUsername", data.username);
localStorage.setItem("otpSentTime", now.toString());
// navigate("/auth/login-otp");
navigate("/dashboard",{ replace: true });
navigate("/dashboard", { replace: true });
}
} catch (err) {
showToast("Invalid username or password.", "error");
@ -78,14 +78,13 @@ const LoginPage = () => {
}, [IsLoginWithOTP]);
useEffect(() => {
const token =
localStorage.getItem("jwtToken") ||
sessionStorage.getItem("jwtToken");
const token =
localStorage.getItem("jwtToken") || sessionStorage.getItem("jwtToken");
if (token) {
navigate("/dashboard", { replace: true });
}
}, []);
if (token) {
navigate("/dashboard", { replace: true });
}
}, []);
return (
<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>
<Link
to="/auth/forgot-password"
className="text-decoration-none"
className="text-decoration-none text-green"
>
Forgot Password?
</Link>
@ -191,11 +190,7 @@ const LoginPage = () => {
)}
{/* Submit */}
<button
type="submit"
className="btn btn-primary w-100"
disabled={loading}
>
<button type="submit" className=" btn-green w-100" disabled={loading}>
{loading
? "Please Wait..."
: IsLoginWithOTP
@ -211,7 +206,7 @@ const LoginPage = () => {
</div>
<button
type="button"
className="btn btn-outline-secondary w-100"
className="btn-green btn-green-outline w-100"
onClick={() => setLoginWithOtp(true)}
>
Login With OTP
@ -224,17 +219,20 @@ const LoginPage = () => {
{!IsLoginWithOTP ? (
<p className="text-center mt-3">
<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
</Link>
</p>
) : (
<div className="text-center mt-3">
<button
className="btn btn-link p-0"
className="btn btn-link p-0 text-green"
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
</button>
</div>

View File

@ -21,7 +21,6 @@ const LoginWithOtp = () => {
const [loading, setLoading] = useState(false);
const [timeLeft, setTimeLeft] = useState(0);
const inputRefs = useRef([]);
const {
@ -43,17 +42,16 @@ const LoginWithOtp = () => {
try {
let requestedData = {
email: username,
otp: finalOtp
}
const response = await AuthRepository.verifyOTP(requestedData)
otp: finalOtp,
};
const response = await AuthRepository.verifyOTP(requestedData);
localStorage.setItem("jwtToken", response.data.token);
localStorage.setItem("refreshToken", response.data.refreshToken);
setLoading(false);
localStorage.removeItem("otpUsername");
localStorage.removeItem("otpSentTime");
navigate("/auth/switch/org");
navigate("/auth/switch/org");
} catch (err) {
showToast("Invalid or expired OTP.", "error");
@ -61,7 +59,9 @@ const LoginWithOtp = () => {
}
};
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");
return `${min}:${sec}`;
};
@ -78,7 +78,6 @@ const LoginWithOtp = () => {
}
}, []);
useEffect(() => {
if (timeLeft <= 0) return;
@ -112,22 +111,22 @@ const LoginWithOtp = () => {
}
trigger(["otp1", "otp2", "otp3", "otp4"]);
} 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++) {
setValue(`otp${i + 1}`, "")
setValue(`otp${i + 1}`, "");
}
}
}
};
return (
// <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="block p-4 p-sm-5 bg-gray-60">
<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">
<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)}>
<div className="d-flex justify-content-center gap-6 mb-3">
@ -139,8 +138,9 @@ const LoginWithOtp = () => {
key={num}
type="text"
maxLength={1}
className={`form-control text-center ${errors[`otp${num}`] ? "is-invalid" : ""
}`}
className={`form-control text-center ${
errors[`otp${num}`] ? "is-invalid" : ""
}`}
ref={(el) => {
inputRefs.current[idx] = el;
ref(el);
@ -150,7 +150,6 @@ const LoginWithOtp = () => {
onChange(e);
if (/^\d$/.test(val) && idx < 3) {
inputRefs.current[idx + 1]?.focus();
} else if (val === "" && idx > 0) {
inputRefs.current[idx - 1]?.focus();
}
@ -164,7 +163,6 @@ const LoginWithOtp = () => {
inputRefs.current[idx - 1]?.focus();
}
}}
onPaste={idx === 0 ? handlePaste : undefined}
style={{ width: "40px", height: "40px", fontSize: "15px" }}
{...rest}
@ -184,7 +182,7 @@ const LoginWithOtp = () => {
<button
type="submit"
className="btn btn-primary d-grid w-100"
className="btn-green d-grid w-100"
disabled={loading}
>
{loading ? "Verifying..." : "Verify OTP"}
@ -199,19 +197,20 @@ const LoginWithOtp = () => {
</p>
) : (
<div>
<p
className="text-center text-danger mt-2 text small-text m-0"
>
<p className="text-center text-danger mt-2 text small-text m-0">
OTP has expired. Please request a new one.
</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>
)}
</form>
</div>
</div>
</div>
// </AuthWrapper>
);
};