diff --git a/src/App.css b/src/App.css new file mode 100644 index 0000000..cb0eadc --- /dev/null +++ b/src/App.css @@ -0,0 +1,180 @@ +.App { + text-align: center; +} + +.App-header { + background-color: #282c34; + padding: 20px; + color: white; +} + +.container-fluid { + padding: 20px; +} + +/* Dark mode support */ +.dark-mode { + background-color: #1f1f1f; + color: #ffffff; +} + +.dark-mode .ant-layout { + background-color: #1f1f1f; +} + +.dark-mode .ant-layout-content { + background-color: #1f1f1f; +} + +/* Calendar custom styles */ +.fc { + background-color: white; + border-radius: 8px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.dark-mode .fc { + background-color: #2d2d2d; + color: #ffffff; +} + +.dark-mode .fc-theme-standard td, +.dark-mode .fc-theme-standard th { + border-color: #404040; +} + +.dark-mode .fc-theme-standard .fc-scrollgrid { + border-color: #404040; +} + +.dark-mode .fc-col-header-cell { + background-color: #3d3d3d; +} + +.dark-mode .fc-daygrid-day { + background-color: #2d2d2d; +} + +.dark-mode .fc-daygrid-day:hover { + background-color: #404040; +} + +/* Project tracker styles */ +.project-card { + margin-bottom: 16px; + border-radius: 8px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.dark-mode .project-card { + background-color: #2d2d2d; + border-color: #404040; +} + +.progress-bar { + border-radius: 4px; +} + +.status-badge { + border-radius: 12px; + padding: 4px 12px; + font-size: 12px; + font-weight: 500; +} + +.status-active { + background-color: #52c41a; + color: white; +} + +.status-pending { + background-color: #faad14; + color: white; +} + +.status-completed { + background-color: #1890ff; + color: white; +} + +.status-cancelled { + background-color: #ff4d4f; + color: white; +} + +/* Navigation styles */ +.navbar-brand { + font-weight: bold; + font-size: 1.5rem; +} + +.nav-link { + font-weight: 500; + transition: color 0.3s ease; +} + +.nav-link:hover { + color: #1890ff !important; +} + +.nav-link.active { + color: #1890ff !important; + font-weight: 600; +} + +/* Responsive design */ +@media (max-width: 768px) { + .container-fluid { + padding: 10px; + } + + .project-card { + margin-bottom: 12px; + } + + .fc { + font-size: 14px; + } +} + +/* Loading animation */ +.loading-spinner { + display: flex; + justify-content: center; + align-items: center; + height: 200px; +} + +.loading-spinner .ant-spin { + font-size: 24px; +} + +/* Custom scrollbar */ +::-webkit-scrollbar { + width: 8px; +} + +::-webkit-scrollbar-track { + background: #f1f1f1; +} + +::-webkit-scrollbar-thumb { + background: #c1c1c1; + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover { + background: #a8a8a8; +} + +.dark-mode ::-webkit-scrollbar-track { + background: #2d2d2d; +} + +.dark-mode ::-webkit-scrollbar-thumb { + background: #555; +} + +.dark-mode ::-webkit-scrollbar-thumb:hover { + background: #777; +} diff --git a/src/App.js b/src/App.js new file mode 100644 index 0000000..6baff05 --- /dev/null +++ b/src/App.js @@ -0,0 +1,25 @@ +import React from 'react'; +import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'; +import Calendar from './pages/Calendar'; +import ProjectTracker from './pages/ProjectTracker'; +import Navigation from './components/Navigation'; +import 'bootstrap/dist/css/bootstrap.min.css'; +import 'antd/dist/reset.css'; +import './App.css'; + +function App() { + return ( + +
+ + + } /> + } /> + } /> + +
+
+ ); +} + +export default App; diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..6baff05 --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'; +import Calendar from './pages/Calendar'; +import ProjectTracker from './pages/ProjectTracker'; +import Navigation from './components/Navigation'; +import 'bootstrap/dist/css/bootstrap.min.css'; +import 'antd/dist/reset.css'; +import './App.css'; + +function App() { + return ( + +
+ + + } /> + } /> + } /> + +
+
+ ); +} + +export default App; diff --git a/src/Router/all_routes.jsx b/src/Router/all_routes.jsx index fb70916..5c04373 100644 --- a/src/Router/all_routes.jsx +++ b/src/Router/all_routes.jsx @@ -194,4 +194,6 @@ export const all_routes = { warehouses: "/warehouse", coupons:"/coupons", weddingGuestList: "/wedding-guest-list", + addWeddingGuest: "/add-wedding-guest", + editWeddingGuest: "/edit-wedding-guest/:id", }; diff --git a/src/Router/router.link.jsx b/src/Router/router.link.jsx index b299828..9d92123 100644 --- a/src/Router/router.link.jsx +++ b/src/Router/router.link.jsx @@ -199,6 +199,8 @@ import ProjectTracker from "../feature-module/projects/projecttracker"; import CreateProject from "../feature-module/projects/createproject"; import EnhancedLoaders from "../feature-module/uiinterface/enhanced-loaders"; import WeddingGuestList from "../feature-module/inventory/weddingGuestList"; +import EditWeddingGuest from "../feature-module/inventory/editWeddingGuest"; +import AddWeddingGuest from "../feature-module/inventory/addWeddingGuest"; import ProductList2 from "../feature-module/inventory/productlist2"; import ProductList3 from "../feature-module/inventory/productlist3"; import { all_routes } from "./all_routes"; @@ -1451,6 +1453,20 @@ export const publicRoutes = [ element: , route: Route, }, + { + id: 117.3, + path: routes.editWeddingGuest, + name: "editWeddingGuest", + element: , + route: Route, + }, + { + id: 117.4, + path: routes.addWeddingGuest, + name: "addWeddingGuest", + element: , + route: Route, + }, { id: 118, path: "/", diff --git a/src/components/Navigation.js b/src/components/Navigation.js new file mode 100644 index 0000000..5fed6ba --- /dev/null +++ b/src/components/Navigation.js @@ -0,0 +1,107 @@ +import React from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { Calendar, Target } from 'feather-icons-react'; + +const Navigation = () => { + const location = useLocation(); + + const navItems = [ + { + path: '/calendar', + name: 'Calendar', + icon: , + description: 'Quản lý lịch trình và sự kiện' + }, + { + path: '/projects', + name: 'Project Tracker', + icon: , + description: 'Theo dõi tiến độ dự án' + } + ]; + + return ( + + ); +}; + +export default Navigation; diff --git a/src/components/Navigation.tsx b/src/components/Navigation.tsx new file mode 100644 index 0000000..3f2ad02 --- /dev/null +++ b/src/components/Navigation.tsx @@ -0,0 +1,118 @@ +import React, { useState } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { Calendar, Target, Moon, Sun } from 'feather-icons-react'; + +const Navigation: React.FC = () => { + const [darkMode, setDarkMode] = useState(false); + const location = useLocation(); + + const toggleDarkMode = () => { + setDarkMode(!darkMode); + document.body.classList.toggle('dark-mode'); + }; + + const isActive = (path: string) => { + return location.pathname === path; + }; + + return ( + + ); +}; + +export default Navigation; diff --git a/src/feature-module/inventory/addWeddingGuest.jsx b/src/feature-module/inventory/addWeddingGuest.jsx new file mode 100644 index 0000000..b97332c --- /dev/null +++ b/src/feature-module/inventory/addWeddingGuest.jsx @@ -0,0 +1,364 @@ +import React, { useState } from 'react'; +import { Form, Input, InputNumber, Select, Button, Card, message, Row, Col } from 'antd'; +import { useNavigate, Link } from 'react-router-dom'; +import { ArrowLeft, Save, Heart } from 'react-feather'; +import { weddingGuestService } from '../../services/weddingGuestService'; + +const { Option } = Select; +const { TextArea } = Input; + +const AddWeddingGuest = () => { + const navigate = useNavigate(); + const [form] = Form.useForm(); + const [submitting, setSubmitting] = useState(false); + + // Handle form submission + const handleSubmit = async (values) => { + setSubmitting(true); + try { + console.log('📤 Creating guest with values:', values); + + // Prepare create data according to API model (không gửi id, createdDate, createdBy) + const createData = { + name: values.name, + unit: values.unit, + numberOfPeople: values.numberOfPeople, + giftAmount: values.giftAmount, + status: values.status, + relationship: values.relationship, + notes: values.notes || '', + updatedDate: new Date().toISOString(), + updatedBy: 'current-user', // You might want to get this from auth context + isActive: true + }; + + console.log('📤 Final create data:', createData); + + const response = await weddingGuestService.createWeddingGuest(createData); + + if (response.success) { + message.success('Thêm khách mời thành công!'); + navigate('/wedding-guest-list'); + } else { + message.error(response.message || 'Failed to create guest'); + } + } catch (error) { + console.error('Error creating guest:', error); + message.error('An error occurred while creating guest'); + } finally { + setSubmitting(false); + } + }; + + return ( +
+ +
+ {/* Header */} +
+
+
+

+ + Thêm khách mời đám cưới +

+
Thêm khách mời mới vào danh sách
+
+
+
+ + + +
+
+ + {/* Form */} + +
+ + + + + + + + + + + + + + + + + + + + + + + + `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} + parser={value => value.replace(/\$\s?|(,*)/g, '')} + /> + + + + + + + + + + + + + + + + + + + + + +