diff --git a/src/Router/router.link.jsx b/src/Router/router.link.jsx
index ab49cad..bf63ff0 100644
--- a/src/Router/router.link.jsx
+++ b/src/Router/router.link.jsx
@@ -196,6 +196,8 @@ import Coupons from "../feature-module/coupons/coupons";
import ApiTest from "../components/ApiTest";
import TodoList from "../feature-module/todo/todolist";
import ProjectTracker from "../feature-module/projects/projecttracker";
+import CreateProject from "../feature-module/projects/createproject";
+import EnhancedLoaders from "../feature-module/uiinterface/enhanced-loaders";
import { all_routes } from "./all_routes";
export const publicRoutes = [
{
@@ -411,6 +413,13 @@ export const publicRoutes = [
element: ,
route: Route,
},
+ {
+ id: 29.1,
+ path: "/enhanced-loaders",
+ name: "enhanced-loaders",
+ element: ,
+ route: Route,
+ },
{
id: 30,
path: routes.carousel,
@@ -1411,6 +1420,13 @@ export const publicRoutes = [
element: ,
route: Route,
},
+ {
+ id: 117.1,
+ path: "/create-project",
+ name: "createproject",
+ element: ,
+ route: Route,
+ },
{
id: 118,
path: "/",
diff --git a/src/components/Loading/EnhancedLoader.jsx b/src/components/Loading/EnhancedLoader.jsx
new file mode 100644
index 0000000..cfc38ca
--- /dev/null
+++ b/src/components/Loading/EnhancedLoader.jsx
@@ -0,0 +1,133 @@
+import React, { useState, useEffect } from 'react';
+import './EnhancedLoader.scss';
+
+const EnhancedLoader = ({
+ type = 'modern',
+ size = 'medium',
+ color = 'primary',
+ text = 'Loading...',
+ showText = true,
+ overlay = true,
+ progress = null
+}) => {
+ const [dots, setDots] = useState('');
+
+ useEffect(() => {
+ const interval = setInterval(() => {
+ setDots(prev => prev.length >= 3 ? '' : prev + '.');
+ }, 500);
+
+ return () => clearInterval(interval);
+ }, []);
+
+ const renderLoader = () => {
+ switch (type) {
+ case 'modern':
+ return (
+
+ );
+
+ case 'pulse':
+ return (
+
+ );
+
+ case 'wave':
+ return (
+
+ );
+
+ case 'spinner':
+ return (
+
+ );
+
+ case 'dots':
+ return (
+
+ );
+
+ case 'gradient':
+ return (
+
+ );
+
+ case 'bounce':
+ return (
+
+ );
+
+ default:
+ return (
+
+ );
+ }
+ };
+
+ return (
+
+
+ {renderLoader()}
+
+ {showText && (
+
+
{text}{dots}
+ {progress !== null && (
+
+ )}
+
+ )}
+
+
+ );
+};
+
+export default EnhancedLoader;
diff --git a/src/components/Loading/EnhancedLoader.scss b/src/components/Loading/EnhancedLoader.scss
new file mode 100644
index 0000000..8f356a8
--- /dev/null
+++ b/src/components/Loading/EnhancedLoader.scss
@@ -0,0 +1,362 @@
+// Enhanced Loader Styles
+.enhanced-loader-container {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ min-height: 200px;
+
+ &.with-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100vh;
+ background: rgba(255, 255, 255, 0.95);
+ backdrop-filter: blur(5px);
+ z-index: 999999;
+
+ [data-layout-mode="dark_mode"] & {
+ background: rgba(29, 29, 66, 0.95);
+ }
+ }
+}
+
+.enhanced-loader-content {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 20px;
+}
+
+// Size variants
+.small {
+ transform: scale(0.7);
+}
+
+.medium {
+ transform: scale(1);
+}
+
+.large {
+ transform: scale(1.3);
+}
+
+// Color variants
+.primary {
+ --loader-color: #ff9f43;
+ --loader-secondary: rgba(255, 159, 67, 0.3);
+}
+
+.success {
+ --loader-color: #28a745;
+ --loader-secondary: rgba(40, 167, 69, 0.3);
+}
+
+.danger {
+ --loader-color: #dc3545;
+ --loader-secondary: rgba(220, 53, 69, 0.3);
+}
+
+.info {
+ --loader-color: #17a2b8;
+ --loader-secondary: rgba(23, 162, 184, 0.3);
+}
+
+// Modern Ring Loader
+.modern-loader {
+ .loader-ring {
+ display: inline-block;
+ position: relative;
+ width: 80px;
+ height: 80px;
+
+ div {
+ box-sizing: border-box;
+ display: block;
+ position: absolute;
+ width: 64px;
+ height: 64px;
+ margin: 8px;
+ border: 8px solid var(--loader-color);
+ border-radius: 50%;
+ animation: modern-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
+ border-color: var(--loader-color) transparent transparent transparent;
+
+ &:nth-child(1) { animation-delay: -0.45s; }
+ &:nth-child(2) { animation-delay: -0.3s; }
+ &:nth-child(3) { animation-delay: -0.15s; }
+ }
+ }
+}
+
+@keyframes modern-ring {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+// Pulse Loader
+.pulse-loader {
+ display: flex;
+ gap: 8px;
+
+ .pulse-dot {
+ width: 16px;
+ height: 16px;
+ border-radius: 50%;
+ background: var(--loader-color);
+ animation: pulse-scale 1.4s ease-in-out infinite both;
+
+ &:nth-child(1) { animation-delay: -0.32s; }
+ &:nth-child(2) { animation-delay: -0.16s; }
+ &:nth-child(3) { animation-delay: 0s; }
+ }
+}
+
+@keyframes pulse-scale {
+ 0%, 80%, 100% {
+ transform: scale(0);
+ opacity: 0.5;
+ }
+ 40% {
+ transform: scale(1);
+ opacity: 1;
+ }
+}
+
+// Wave Loader
+.wave-loader {
+ display: flex;
+ gap: 4px;
+ align-items: end;
+
+ .wave-bar {
+ width: 8px;
+ height: 40px;
+ background: var(--loader-color);
+ border-radius: 4px;
+ animation: wave-bounce 1.2s ease-in-out infinite;
+
+ &:nth-child(1) { animation-delay: -1.1s; }
+ &:nth-child(2) { animation-delay: -1.0s; }
+ &:nth-child(3) { animation-delay: -0.9s; }
+ &:nth-child(4) { animation-delay: -0.8s; }
+ &:nth-child(5) { animation-delay: -0.7s; }
+ }
+}
+
+@keyframes wave-bounce {
+ 0%, 40%, 100% {
+ transform: scaleY(0.4);
+ }
+ 20% {
+ transform: scaleY(1.0);
+ }
+}
+
+// Spinner Loader
+.spinner-loader {
+ .spinner-circle {
+ width: 60px;
+ height: 60px;
+ border: 6px solid var(--loader-secondary);
+ border-top: 6px solid var(--loader-color);
+ border-radius: 50%;
+ animation: spinner-rotate 1s linear infinite;
+ position: relative;
+
+ .spinner-inner {
+ width: 30px;
+ height: 30px;
+ border: 3px solid var(--loader-secondary);
+ border-top: 3px solid var(--loader-color);
+ border-radius: 50%;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ animation: spinner-rotate 0.5s linear infinite reverse;
+ }
+ }
+}
+
+@keyframes spinner-rotate {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+// Dots Loader
+.dots-loader {
+ display: flex;
+ gap: 6px;
+
+ .dot {
+ width: 12px;
+ height: 12px;
+ border-radius: 50%;
+ background: var(--loader-color);
+ animation: dots-bounce 1.4s ease-in-out infinite both;
+
+ &:nth-child(1) { animation-delay: -0.32s; }
+ &:nth-child(2) { animation-delay: -0.16s; }
+ &:nth-child(3) { animation-delay: 0s; }
+ &:nth-child(4) { animation-delay: 0.16s; }
+ &:nth-child(5) { animation-delay: 0.32s; }
+ }
+}
+
+@keyframes dots-bounce {
+ 0%, 80%, 100% {
+ transform: scale(0);
+ }
+ 40% {
+ transform: scale(1);
+ }
+}
+
+// Gradient Loader
+.gradient-loader {
+ .gradient-spinner {
+ width: 60px;
+ height: 60px;
+ border-radius: 50%;
+ background: conic-gradient(
+ from 0deg,
+ var(--loader-color),
+ var(--loader-secondary),
+ var(--loader-color)
+ );
+ animation: gradient-spin 1.5s linear infinite;
+ position: relative;
+
+ &::before {
+ content: '';
+ position: absolute;
+ top: 6px;
+ left: 6px;
+ right: 6px;
+ bottom: 6px;
+ border-radius: 50%;
+ background: white;
+
+ [data-layout-mode="dark_mode"] & {
+ background: #1d1d42;
+ }
+ }
+ }
+}
+
+@keyframes gradient-spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+// Bounce Loader
+.bounce-loader {
+ display: flex;
+ gap: 8px;
+
+ .bounce-ball {
+ width: 18px;
+ height: 18px;
+ border-radius: 50%;
+ background: var(--loader-color);
+ animation: bounce-up-down 1.4s ease-in-out infinite both;
+
+ &:nth-child(1) { animation-delay: -0.32s; }
+ &:nth-child(2) { animation-delay: -0.16s; }
+ &:nth-child(3) { animation-delay: 0s; }
+ }
+}
+
+@keyframes bounce-up-down {
+ 0%, 80%, 100% {
+ transform: translateY(0);
+ }
+ 40% {
+ transform: translateY(-30px);
+ }
+}
+
+// Loader Text
+.loader-text {
+ text-align: center;
+
+ .loading-message {
+ font-size: 16px;
+ font-weight: 500;
+ color: #333;
+ margin-bottom: 10px;
+ display: block;
+
+ [data-layout-mode="dark_mode"] & {
+ color: #ffffff;
+ }
+ }
+
+ .progress-container {
+ margin-top: 15px;
+ width: 200px;
+
+ .progress-bar {
+ width: 100%;
+ height: 6px;
+ background: #e9ecef;
+ border-radius: 3px;
+ overflow: hidden;
+ margin-bottom: 8px;
+
+ [data-layout-mode="dark_mode"] & {
+ background: #67748E;
+ }
+
+ .progress-fill {
+ height: 100%;
+ background: var(--loader-color);
+ border-radius: 3px;
+ transition: width 0.3s ease;
+ background: linear-gradient(
+ 90deg,
+ var(--loader-color),
+ var(--loader-secondary),
+ var(--loader-color)
+ );
+ background-size: 200% 100%;
+ animation: progress-shimmer 2s ease-in-out infinite;
+ }
+ }
+
+ .progress-text {
+ font-size: 14px;
+ color: #666;
+ font-weight: 500;
+
+ [data-layout-mode="dark_mode"] & {
+ color: #67748E;
+ }
+ }
+ }
+}
+
+@keyframes progress-shimmer {
+ 0% { background-position: -200% 0; }
+ 100% { background-position: 200% 0; }
+}
+
+// Responsive adjustments
+@media (max-width: 768px) {
+ .enhanced-loader-content {
+ gap: 15px;
+ }
+
+ .small { transform: scale(0.6); }
+ .medium { transform: scale(0.8); }
+ .large { transform: scale(1); }
+
+ .loader-text .loading-message {
+ font-size: 14px;
+ }
+
+ .progress-container {
+ width: 150px;
+ }
+}
diff --git a/src/components/Loading/LoadingButton.jsx b/src/components/Loading/LoadingButton.jsx
new file mode 100644
index 0000000..31f0506
--- /dev/null
+++ b/src/components/Loading/LoadingButton.jsx
@@ -0,0 +1,64 @@
+import React from 'react';
+import './LoadingButton.scss';
+
+const LoadingButton = ({
+ loading = false,
+ children,
+ className = '',
+ variant = 'primary',
+ size = 'medium',
+ disabled = false,
+ loadingText = 'Loading...',
+ spinnerType = 'spinner',
+ onClick,
+ type = 'button',
+ ...props
+}) => {
+ const handleClick = (e) => {
+ if (!loading && !disabled && onClick) {
+ onClick(e);
+ }
+ };
+
+ const renderSpinner = () => {
+ switch (spinnerType) {
+ case 'spinner':
+ return ;
+ case 'dots':
+ return (
+
+ );
+ case 'pulse':
+ return ;
+ default:
+ return ;
+ }
+ };
+
+ return (
+
+ );
+};
+
+export default LoadingButton;
diff --git a/src/components/Loading/LoadingButton.scss b/src/components/Loading/LoadingButton.scss
new file mode 100644
index 0000000..94b638b
--- /dev/null
+++ b/src/components/Loading/LoadingButton.scss
@@ -0,0 +1,261 @@
+// Loading Button Styles
+.loading-btn {
+ position: relative;
+ border: none;
+ border-radius: 6px;
+ font-weight: 500;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ overflow: hidden;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ min-width: 120px;
+
+ &:focus {
+ outline: none;
+ box-shadow: 0 0 0 3px rgba(255, 159, 67, 0.3);
+ }
+
+ // Size variants
+ &.small {
+ padding: 8px 16px;
+ font-size: 14px;
+ min-width: 80px;
+ }
+
+ &.medium {
+ padding: 10px 20px;
+ font-size: 16px;
+ min-width: 120px;
+ }
+
+ &.large {
+ padding: 12px 24px;
+ font-size: 18px;
+ min-width: 140px;
+ }
+
+ // Color variants
+ &.primary {
+ background: #ff9f43;
+ color: white;
+
+ &:hover:not(.loading):not(.disabled) {
+ background: #e8890a;
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(255, 159, 67, 0.4);
+ }
+ }
+
+ &.secondary {
+ background: #6c757d;
+ color: white;
+
+ &:hover:not(.loading):not(.disabled) {
+ background: #5a6268;
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(108, 117, 125, 0.4);
+ }
+ }
+
+ &.success {
+ background: #28a745;
+ color: white;
+
+ &:hover:not(.loading):not(.disabled) {
+ background: #218838;
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(40, 167, 69, 0.4);
+ }
+ }
+
+ &.danger {
+ background: #dc3545;
+ color: white;
+
+ &:hover:not(.loading):not(.disabled) {
+ background: #c82333;
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(220, 53, 69, 0.4);
+ }
+ }
+
+ &.outline-primary {
+ background: transparent;
+ color: #ff9f43;
+ border: 2px solid #ff9f43;
+
+ &:hover:not(.loading):not(.disabled) {
+ background: #ff9f43;
+ color: white;
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(255, 159, 67, 0.4);
+ }
+ }
+
+ // Loading state
+ &.loading {
+ cursor: not-allowed;
+ opacity: 0.8;
+
+ &::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: -100%;
+ width: 100%;
+ height: 100%;
+ background: linear-gradient(
+ 90deg,
+ transparent,
+ rgba(255, 255, 255, 0.2),
+ transparent
+ );
+ animation: loading-shimmer 1.5s infinite;
+ }
+ }
+
+ // Disabled state
+ &.disabled {
+ cursor: not-allowed;
+ opacity: 0.6;
+ background: #e9ecef !important;
+ color: #6c757d !important;
+ border-color: #e9ecef !important;
+
+ &:hover {
+ transform: none !important;
+ box-shadow: none !important;
+ }
+ }
+
+ // Button content
+ .btn-content {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+ transition: all 0.3s ease;
+
+ &.loading {
+ .btn-text {
+ opacity: 0.8;
+ }
+ }
+ }
+
+ .btn-loader {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .btn-text {
+ transition: opacity 0.3s ease;
+ }
+
+ // Spinner animations
+ .btn-spinner {
+ width: 16px;
+ height: 16px;
+ border: 2px solid rgba(255, 255, 255, 0.3);
+ border-top: 2px solid currentColor;
+ border-radius: 50%;
+ animation: btn-spin 1s linear infinite;
+ }
+
+ .btn-dots {
+ display: flex;
+ gap: 3px;
+
+ .dot {
+ width: 4px;
+ height: 4px;
+ border-radius: 50%;
+ background: currentColor;
+ animation: btn-dots-bounce 1.4s ease-in-out infinite both;
+
+ &:nth-child(1) { animation-delay: -0.32s; }
+ &:nth-child(2) { animation-delay: -0.16s; }
+ &:nth-child(3) { animation-delay: 0s; }
+ }
+ }
+
+ .btn-pulse {
+ width: 12px;
+ height: 12px;
+ border-radius: 50%;
+ background: currentColor;
+ animation: btn-pulse-scale 1s ease-in-out infinite;
+ }
+}
+
+// Animations
+@keyframes loading-shimmer {
+ 0% { left: -100%; }
+ 100% { left: 100%; }
+}
+
+@keyframes btn-spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+@keyframes btn-dots-bounce {
+ 0%, 80%, 100% {
+ transform: scale(0);
+ }
+ 40% {
+ transform: scale(1);
+ }
+}
+
+@keyframes btn-pulse-scale {
+ 0%, 100% {
+ transform: scale(1);
+ opacity: 1;
+ }
+ 50% {
+ transform: scale(1.2);
+ opacity: 0.7;
+ }
+}
+
+// Dark mode support
+[data-layout-mode="dark_mode"] {
+ .loading-btn {
+ &.disabled {
+ background: #67748E !important;
+ color: #1d1d42 !important;
+ border-color: #67748E !important;
+ }
+
+ &:focus {
+ box-shadow: 0 0 0 3px rgba(255, 159, 67, 0.4);
+ }
+ }
+}
+
+// Responsive adjustments
+@media (max-width: 768px) {
+ .loading-btn {
+ &.small {
+ padding: 6px 12px;
+ font-size: 13px;
+ min-width: 70px;
+ }
+
+ &.medium {
+ padding: 8px 16px;
+ font-size: 14px;
+ min-width: 100px;
+ }
+
+ &.large {
+ padding: 10px 20px;
+ font-size: 16px;
+ min-width: 120px;
+ }
+ }
+}
diff --git a/src/components/Loading/index.js b/src/components/Loading/index.js
new file mode 100644
index 0000000..eb7d54c
--- /dev/null
+++ b/src/components/Loading/index.js
@@ -0,0 +1,2 @@
+export { default as EnhancedLoader } from './EnhancedLoader';
+export { default as LoadingButton } from './LoadingButton';
diff --git a/src/feature-module/loader/loader.jsx b/src/feature-module/loader/loader.jsx
index b75486e..fd1322e 100644
--- a/src/feature-module/loader/loader.jsx
+++ b/src/feature-module/loader/loader.jsx
@@ -1,41 +1,68 @@
import React, { useEffect, useState } from 'react';
-import { Route,Routes, useLocation } from 'react-router-dom';
+import { Route, Routes, useLocation } from 'react-router-dom';
+import { EnhancedLoader } from '../../components/Loading';
const Loader = () => {
const [loading, setLoading] = useState(false);
+ const [progress, setProgress] = useState(0);
const location = useLocation();
const showLoader = () => {
setLoading(true);
+ setProgress(0);
};
const hideLoader = () => {
setLoading(false);
+ setProgress(100);
window.scrollTo(0, 0);
};
useEffect(() => {
showLoader();
+
+ // Simulate loading progress
+ const progressInterval = setInterval(() => {
+ setProgress(prev => {
+ if (prev >= 90) {
+ clearInterval(progressInterval);
+ return 90;
+ }
+ return prev + Math.random() * 30;
+ });
+ }, 100);
+
const timeoutId = setTimeout(() => {
- hideLoader();
- }, 600);
+ clearInterval(progressInterval);
+ setProgress(100);
+ setTimeout(() => {
+ hideLoader();
+ }, 200);
+ }, 800);
return () => {
clearTimeout(timeoutId);
+ clearInterval(progressInterval);
};
- }, [location.pathname]); // Trigger useEffect when the pathname changes
+ }, [location.pathname]);
return (
- {loading && (
-
- )}
+ {loading && (
+
+ )}
-
+
);
};
diff --git a/src/feature-module/projects/createproject.jsx b/src/feature-module/projects/createproject.jsx
new file mode 100644
index 0000000..fa00dcf
--- /dev/null
+++ b/src/feature-module/projects/createproject.jsx
@@ -0,0 +1,461 @@
+import React, { useState } from 'react';
+import { Link } from 'react-router-dom';
+import { DatePicker, Select, Input } from 'antd';
+import {
+ ArrowLeft,
+ Calendar,
+ Users,
+ DollarSign,
+ Target,
+ Clock,
+ FileText
+} from 'feather-icons-react';
+import { LoadingButton } from '../../components/Loading';
+import dayjs from 'dayjs';
+
+const { Option } = Select;
+const { TextArea } = Input;
+
+const CreateProject = () => {
+ const [loading, setLoading] = useState(false);
+ const [formData, setFormData] = useState({
+ projectName: '',
+ description: '',
+ category: '',
+ priority: 'medium',
+ status: 'planning',
+ startDate: dayjs(),
+ endDate: dayjs().add(1, 'month'),
+ budget: '',
+ client: '',
+ manager: [],
+ teamMembers: [],
+ tags: [],
+ attachments: []
+ });
+
+ const [errors, setErrors] = useState({});
+
+ // Avatar component with initials fallback
+ const UserAvatar = ({ initials, name }) => (
+
+ {initials}
+
+ );
+
+ // Sample data
+ const categories = [
+ { value: 'web-development', label: 'Web Development', color: 'blue' },
+ { value: 'mobile-app', label: 'Mobile App', color: 'green' },
+ { value: 'design', label: 'Design', color: 'purple' },
+ { value: 'marketing', label: 'Marketing', color: 'orange' },
+ { value: 'devops', label: 'DevOps', color: 'cyan' },
+ { value: 'data-science', label: 'Data Science', color: 'red' }
+ ];
+
+ const managers = [
+ { value: 'john-smith', label: 'John Smith', initials: 'JS' },
+ { value: 'sarah-johnson', label: 'Sarah Johnson', initials: 'SJ' },
+ { value: 'mike-wilson', label: 'Mike Wilson', initials: 'MW' },
+ { value: 'lisa-chen', label: 'Lisa Chen', initials: 'LC' }
+ ];
+
+ const teamMembers = [
+ { value: 'alex-rodriguez', label: 'Alex Rodriguez', initials: 'AR' },
+ { value: 'maria-garcia', label: 'Maria Garcia', initials: 'MG' },
+ { value: 'david-brown', label: 'David Brown', initials: 'DB' },
+ { value: 'emma-davis', label: 'Emma Davis', initials: 'ED' },
+ { value: 'james-miller', label: 'James Miller', initials: 'JM' }
+ ];
+
+ const handleInputChange = (field, value) => {
+ setFormData(prev => ({
+ ...prev,
+ [field]: value
+ }));
+
+ // Clear error when user starts typing
+ if (errors[field]) {
+ setErrors(prev => ({
+ ...prev,
+ [field]: ''
+ }));
+ }
+ };
+
+ const validateForm = () => {
+ const newErrors = {};
+
+ if (!formData.projectName.trim()) {
+ newErrors.projectName = 'Project name is required';
+ }
+
+ if (!formData.description.trim()) {
+ newErrors.description = 'Project description is required';
+ }
+
+ if (!formData.category) {
+ newErrors.category = 'Please select a category';
+ }
+
+ if (!formData.client.trim()) {
+ newErrors.client = 'Client name is required';
+ }
+
+ if (!formData.budget.trim()) {
+ newErrors.budget = 'Budget is required';
+ }
+
+ if (formData.manager.length === 0) {
+ newErrors.manager = 'Please assign at least one manager';
+ }
+
+ if (dayjs(formData.endDate).isBefore(dayjs(formData.startDate))) {
+ newErrors.endDate = 'End date must be after start date';
+ }
+
+ setErrors(newErrors);
+ return Object.keys(newErrors).length === 0;
+ };
+
+ const handleSubmit = async (e) => {
+ e.preventDefault();
+
+ if (!validateForm()) {
+ return;
+ }
+
+ setLoading(true);
+
+ try {
+ // Simulate API call
+ await new Promise(resolve => setTimeout(resolve, 2000));
+
+ console.log('Project created:', formData);
+
+ // Reset form or redirect
+ alert('Project created successfully!');
+
+ } catch (error) {
+ console.error('Error creating project:', error);
+ alert('Error creating project. Please try again.');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+
+
+ return (
+
+
+ {/* Header */}
+
+
+
+
Create New Project
+ Add a new project to your workspace
+
+
+
+
+
+ Back to Projects
+
+
+
+
+ {/* Form */}
+
+
+
+ );
+};
+
+export default CreateProject;
diff --git a/src/feature-module/projects/projecttracker.jsx b/src/feature-module/projects/projecttracker.jsx
index 8108780..e75b02e 100644
--- a/src/feature-module/projects/projecttracker.jsx
+++ b/src/feature-module/projects/projecttracker.jsx
@@ -1,4 +1,5 @@
import React, { useState } from 'react';
+import { Link } from 'react-router-dom';
import { Table, Progress, Tag, Avatar, Button, DatePicker, Select } from 'antd';
import {
Star,
@@ -349,13 +350,15 @@ const ProjectTracker = () => {
- }
- className="btn btn-added"
- >
- Create New Project
-
+
+ }
+ className="btn btn-added"
+ >
+ Create New Project
+
+
diff --git a/src/feature-module/uiinterface/enhanced-loaders.jsx b/src/feature-module/uiinterface/enhanced-loaders.jsx
new file mode 100644
index 0000000..3ad1a9a
--- /dev/null
+++ b/src/feature-module/uiinterface/enhanced-loaders.jsx
@@ -0,0 +1,293 @@
+import React, { useState } from 'react';
+import { EnhancedLoader, LoadingButton } from '../../components/Loading';
+
+const EnhancedLoaders = () => {
+ const [buttonLoading, setButtonLoading] = useState({});
+ const [showLoader, setShowLoader] = useState({});
+
+ const handleButtonClick = (buttonId) => {
+ setButtonLoading(prev => ({ ...prev, [buttonId]: true }));
+
+ setTimeout(() => {
+ setButtonLoading(prev => ({ ...prev, [buttonId]: false }));
+ }, 3000);
+ };
+
+ const toggleLoader = (loaderId) => {
+ setShowLoader(prev => ({ ...prev, [loaderId]: !prev[loaderId] }));
+ };
+
+ return (
+
+
+ {/* Page Header */}
+
+
+
+
Enhanced Loaders
+
Beautiful loading animations and buttons with various styles
+
+
+
+
+ {/* Loading Animations */}
+
+
+
+
+
Modern Ring Loader
+
+
+
+
+ {showLoader.modern && (
+
+ )}
+
+
+
+
+
+
+
+
Pulse Loader
+
+
+
+
+ {showLoader.pulse && (
+
+ )}
+
+
+
+
+
+
+
+
Wave Loader
+
+
+
+
+ {showLoader.wave && (
+
+ )}
+
+
+
+
+
+
+
+
Gradient Spinner
+
+
+
+
+ {showLoader.gradient && (
+
+ )}
+
+
+
+
+
+
+
+
Dots Loader
+
+
+
+
+
+
+
+
+
+
+
Bounce Loader
+
+
+
+
+
+
+
+
+ {/* Loading Buttons */}
+
+
+
+
+
Loading Buttons
+
Interactive buttons with loading states
+
+
+
+
+
Primary Buttons
+
+ handleButtonClick('btn1')}
+ loadingText="Saving..."
+ >
+ Save Changes
+
+
+ handleButtonClick('btn2')}
+ loadingText="Processing..."
+ spinnerType="dots"
+ >
+ Process Data
+
+
+ handleButtonClick('btn3')}
+ loadingText="Uploading..."
+ spinnerType="pulse"
+ >
+ Upload Files
+
+
+
+
+
+
Colored Buttons
+
+ handleButtonClick('btn4')}
+ loadingText="Submitting..."
+ >
+ Submit Form
+
+
+ handleButtonClick('btn5')}
+ loadingText="Deleting..."
+ >
+ Delete Item
+
+
+ handleButtonClick('btn6')}
+ loadingText="Loading..."
+ >
+ Load More
+
+
+
+
+
+
+
+
Disabled State
+
+
+ Disabled Button
+
+
+
+ Also Disabled
+
+
+
+
+
+
+
+
+
+ {/* Size Variations */}
+
+
+
+
+
Size Variations
+
+
+
+
+
Small
+
+
+
+
Medium
+
+
+
+
Large
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default EnhancedLoaders;
diff --git a/src/style/scss/main.scss b/src/style/scss/main.scss
index e42e606..c187b58 100644
--- a/src/style/scss/main.scss
+++ b/src/style/scss/main.scss
@@ -75,4 +75,8 @@
@import "pages/pos-design";
@import "pages/call";
@import "pages/file-manager";
-@import "pages/customisedstyle"
+@import "pages/customisedstyle";
+
+/****** Enhanced Components ******/
+@import "../../components/Loading/EnhancedLoader.scss";
+@import "../../components/Loading/LoadingButton.scss";
diff --git a/src/style/scss/pages/_customisedstyle.scss b/src/style/scss/pages/_customisedstyle.scss
index f7356cd..2fbea81 100644
--- a/src/style/scss/pages/_customisedstyle.scss
+++ b/src/style/scss/pages/_customisedstyle.scss
@@ -514,6 +514,362 @@ $__basecolor: #2c3038;
}
}
+// Create Project Form Styling
+.form-group-header {
+ display: flex;
+ align-items: center;
+ margin-bottom: 20px;
+ padding-bottom: 10px;
+ border-bottom: 2px solid #f0f0f0;
+
+ .form-group-icon {
+ width: 40px;
+ height: 40px;
+ background: linear-gradient(135deg, #ff9f43, #e8890a);
+ border-radius: 8px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-right: 15px;
+ color: white;
+ box-shadow: 0 4px 12px rgba(255, 159, 67, 0.3);
+ }
+
+ h5 {
+ margin: 0;
+ color: #333;
+ font-weight: 600;
+ font-size: 18px;
+ }
+
+ [data-layout-mode="dark_mode"] & {
+ border-bottom-color: #67748E;
+
+ h5 {
+ color: #ffffff;
+ }
+ }
+}
+
+.project-select {
+ width: 100% !important;
+
+ .ant-select-selector {
+ background: #ffffff !important;
+ border: 1px solid #dbe0e6 !important;
+ border-radius: 6px !important;
+ min-height: 42px !important;
+ padding: 8px 12px !important;
+ font-size: 14px;
+ transition: all 0.3s ease;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) !important;
+
+ &:hover {
+ border-color: #ff9f43 !important;
+ box-shadow: 0 2px 6px rgba(255, 159, 67, 0.2) !important;
+ }
+
+ &:focus,
+ &.ant-select-focused {
+ border-color: #ff9f43 !important;
+ box-shadow: 0 0 0 2px rgba(255, 159, 67, 0.2) !important;
+ }
+
+ .ant-select-selection-search {
+ .ant-select-selection-search-input {
+ height: 24px !important;
+ }
+ }
+
+ .ant-select-selection-item {
+ color: #333 !important;
+ font-size: 14px !important;
+ line-height: 24px !important;
+ padding: 0 !important;
+ }
+
+ .ant-select-selection-placeholder {
+ color: #999 !important;
+ font-size: 13px !important;
+ line-height: 24px !important;
+ }
+ }
+
+ .ant-select-arrow {
+ color: #ff9f43 !important;
+ }
+
+ &.ant-select-open .ant-select-selector {
+ border-color: #ff9f43 !important;
+ box-shadow: 0 0 0 2px rgba(255, 159, 67, 0.2) !important;
+ }
+
+ // Multiple selection styling
+ &.ant-select-multiple {
+ .ant-select-selector {
+ min-height: 42px !important;
+ padding: 4px 8px !important;
+ }
+
+ .ant-select-selection-item {
+ background: rgba(255, 159, 67, 0.1) !important;
+ border: 1px solid #ff9f43 !important;
+ border-radius: 4px !important;
+ color: #ff9f43 !important;
+ font-weight: 500 !important;
+ margin: 2px 4px 2px 0 !important;
+ padding: 2px 8px !important;
+ height: auto !important;
+ line-height: 20px !important;
+ display: flex !important;
+ align-items: center !important;
+
+ .ant-select-selection-item-content {
+ flex: 1;
+ }
+
+ .ant-select-selection-item-remove {
+ color: #ff9f43 !important;
+ margin-left: 4px !important;
+
+ &:hover {
+ color: #e8890a !important;
+ }
+ }
+ }
+ }
+
+ // Dark mode
+ [data-layout-mode="dark_mode"] & {
+ .ant-select-selector {
+ background: #1d1d42 !important;
+ border-color: #67748E !important;
+ color: #ffffff !important;
+
+ .ant-select-selection-item {
+ color: #ffffff !important;
+ }
+
+ .ant-select-selection-placeholder {
+ color: #67748E !important;
+ }
+ }
+
+ &.ant-select-multiple .ant-select-selection-item {
+ background: rgba(255, 159, 67, 0.2) !important;
+ color: #ff9f43 !important;
+ }
+ }
+}
+
+// Dropdown styling for project selects
+.ant-select-dropdown {
+ .ant-select-item {
+ padding: 8px 12px !important;
+
+ &:hover {
+ background: rgba(255, 159, 67, 0.1) !important;
+ }
+
+ &.ant-select-item-option-selected {
+ background: rgba(255, 159, 67, 0.2) !important;
+ color: #ff9f43 !important;
+ font-weight: 500 !important;
+ }
+ }
+
+ // Dark mode dropdown
+ [data-layout-mode="dark_mode"] & {
+ background: #1d1d42 !important;
+ border: 1px solid #67748E !important;
+
+ .ant-select-item {
+ color: #ffffff !important;
+
+ &:hover {
+ background: rgba(255, 159, 67, 0.2) !important;
+ color: #ff9f43 !important;
+ }
+
+ &.ant-select-item-option-selected {
+ background: rgba(255, 159, 67, 0.3) !important;
+ color: #ff9f43 !important;
+ }
+ }
+ }
+}
+
+// Form validation styling
+.is-invalid {
+ border-color: #dc3545 !important;
+ box-shadow: 0 0 0 2px rgba(220, 53, 69, 0.2) !important;
+}
+
+// Create Project Button Styling
+.create-project-btn {
+ min-width: 140px !important;
+ height: 40px !important;
+ padding: 8px 20px !important;
+ font-size: 14px !important;
+ font-weight: 500 !important;
+ border-radius: 6px !important;
+
+ &.loading-button {
+ .loading-content {
+ font-size: 14px !important;
+ }
+
+ .loading-spinner {
+ width: 16px !important;
+ height: 16px !important;
+ }
+ }
+}
+
+.btn-cancel-project {
+ min-width: 100px !important;
+ height: 40px !important;
+ padding: 8px 16px !important;
+ font-size: 14px !important;
+ font-weight: 500 !important;
+ border-radius: 6px !important;
+ background: #f8f9fa !important;
+ border: 1px solid #dee2e6 !important;
+ color: #6c757d !important;
+ text-decoration: none !important;
+ display: inline-flex !important;
+ align-items: center !important;
+ justify-content: center !important;
+ transition: all 0.3s ease !important;
+
+ &:hover {
+ background: #e9ecef !important;
+ border-color: #adb5bd !important;
+ color: #495057 !important;
+ text-decoration: none !important;
+ }
+
+ // Dark mode
+ [data-layout-mode="dark_mode"] & {
+ background: #1d1d42 !important;
+ border-color: #67748E !important;
+ color: #ffffff !important;
+
+ &:hover {
+ background: #2a2a5a !important;
+ border-color: #7b8ab8 !important;
+ }
+ }
+}
+
+// Button container styling
+.btn-addproduct {
+ padding: 20px 0 !important;
+
+ &.d-flex {
+ justify-content: flex-start !important;
+
+ .create-project-btn,
+ .btn-cancel-project {
+ margin: 0 !important;
+ }
+ }
+}
+
+.invalid-feedback {
+ display: block;
+ width: 100%;
+ margin-top: 5px;
+ font-size: 13px;
+ color: #dc3545;
+ font-weight: 500;
+}
+
+// Input group styling
+.input-group {
+ .input-group-text {
+ background: #f8f9fa;
+ border: 1px solid #dbe0e6;
+ border-right: none;
+ color: #ff9f43;
+ font-weight: 500;
+
+ [data-layout-mode="dark_mode"] & {
+ background: #67748E;
+ border-color: #67748E;
+ color: #ff9f43;
+ }
+ }
+
+ .form-control {
+ border-left: none;
+
+ &:focus {
+ border-color: #ff9f43;
+ box-shadow: 0 0 0 2px rgba(255, 159, 67, 0.2);
+ }
+ }
+}
+
+// Avatar styling in selects
+.avatar {
+ &.avatar-xs {
+ width: 24px;
+ height: 24px;
+ border-radius: 50%;
+ object-fit: cover;
+ }
+}
+
+// Button styling improvements
+.btn-addproduct {
+ display: flex;
+ align-items: center;
+ gap: 15px;
+ padding: 20px 0;
+ border-top: 1px solid #f0f0f0;
+ margin-top: 30px;
+
+ [data-layout-mode="dark_mode"] & {
+ border-top-color: #67748E;
+ }
+}
+
+.btn-cancel {
+ background: #6c757d;
+ color: white;
+ border: none;
+ padding: 12px 24px;
+ border-radius: 6px;
+ font-weight: 500;
+ transition: all 0.3s ease;
+
+ &:hover {
+ background: #5a6268;
+ color: white;
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(108, 117, 125, 0.4);
+ }
+}
+
+// Badge styling in options
+.badge {
+ display: inline-block;
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+
+ &.badge-blue { background: #007bff; }
+ &.badge-green { background: #28a745; }
+ &.badge-purple { background: #6f42c1; }
+ &.badge-orange { background: #fd7e14; }
+ &.badge-cyan { background: #17a2b8; }
+ &.badge-red { background: #dc3545; }
+ &.badge-success { background: #28a745; }
+ &.badge-warning { background: #ffc107; }
+ &.badge-danger { background: #dc3545; }
+}
+
.swal2-confirm {
background-color: #ff8d1f !important;
border: 1px solid #ff8d1f !important;