fix: sửa lỗi hiển thị trong itineraryTimeline và MemberDashboard

This commit is contained in:
2026-06-24 09:56:05 +07:00
parent f355b9471a
commit 13cd68707e
6 changed files with 39 additions and 26 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 KiB

@@ -278,20 +278,20 @@ export const ItineraryTimeline = ({
<> <>
<button <button
onClick={(e) => { e.stopPropagation(); onAddLocation?.(leg.id, legIdx === 0 && leg.locations.length === 0); }} onClick={(e) => { e.stopPropagation(); onAddLocation?.(leg.id, legIdx === 0 && leg.locations.length === 0); }}
className="p-2 text-gray-400 hover:text-blue-600 hover:bg-blue-50 rounded-xl transition-all" className="p-2 bg-gray-50 text-gray-600 hover:text-blue-600 hover:bg-blue-100 rounded-xl transition-all border border-gray-200"
title="Thêm địa điểm vào chặng này" title="Thêm địa điểm vào chặng này"
> >
<Plus className="w-4 h-4" /> <Plus className="w-4 h-4" />
</button> </button>
<button <button
onClick={(e) => { e.stopPropagation(); handleEditLeg(leg); }} onClick={(e) => { e.stopPropagation(); handleEditLeg(leg); }}
className="p-2 text-gray-400 hover:text-blue-600 hover:bg-blue-50 rounded-xl transition-all" className="p-2 bg-gray-50 text-gray-600 hover:text-blue-600 hover:bg-blue-100 rounded-xl transition-all border border-gray-200"
> >
<Edit2 className="w-4 h-4" /> <Edit2 className="w-4 h-4" />
</button> </button>
<button <button
onClick={(e) => { e.stopPropagation(); handleDeleteLeg(leg.id); }} onClick={(e) => { e.stopPropagation(); handleDeleteLeg(leg.id); }}
className="p-2 text-gray-400 hover:text-red-600 hover:bg-red-50 rounded-xl transition-all" className="p-2 bg-gray-50 text-red-600 hover:text-white-600 hover:bg-red-100 rounded-xl transition-all border border-gray-200"
> >
<Trash2 className="w-4 h-4" /> <Trash2 className="w-4 h-4" />
</button> </button>
@@ -393,7 +393,7 @@ export const ItineraryTimeline = ({
<div key={location.id}> <div key={location.id}>
<div className="relative flex group mb-6"> <div className="relative flex group mb-6">
{/* Timeline Node */} {/* Timeline Node */}
<div className="z-10 mt-1.5 mr-4"> <div className="z-10 -ml-3.5 mr-1.5 mt-1.5">
<button <button
onClick={() => handleStatusClick(location)} onClick={() => handleStatusClick(location)}
className={`transition-colors duration-200 ${location.status === 'COMPLETED' ? 'text-green-500' : 'text-gray-300 hover:text-blue-500'}`} className={`transition-colors duration-200 ${location.status === 'COMPLETED' ? 'text-green-500' : 'text-gray-300 hover:text-blue-500'}`}
+23 -10
View File
@@ -44,25 +44,23 @@
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05); --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1); --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
/* Smooth theme transition */
transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
} }
/* ============ DARK THEME ============ */ /* ============ DARK THEME ============ */
:root.dark { :root.dark {
/* Dark Theme Variables - Vintage Grape & Bondi Blue */ /* Dark Theme Variables - Vintage Grape & Bondi Blue */
--background: #513b56; /* Vintage Grape */ --background: #4b658b; /* Vintage Grape */
--background-alt: #434354; /* Dark Alt */ --background-alt: #2d253f; /* Dark Alt */
--surface: #525174; /* Dusty Grape */ --surface: #515d74; /* Dusty Grape */
--surface-muted: #626186; /* Surface Muted */ --surface-muted: #626186; /* Surface Muted */
--surface-hover: #5f6b7e; /* Surface Hover */ --surface-hover: #5f6b7e; /* Surface Hover */
--border: #626186; /* Border */ --border: #626186; /* Border */
--border-light: #525174; /* Border Light */ --border-light: #525174; /* Border Light */
--text-primary: #f8fafc; /* Soft White */ /* FIX LỖI 1: Thay đổi #173757 thành #f8fafc để chữ có màu trắng sữa chuẩn tương phản cao */
--text-secondary: #cbd5e1; /* Secondary Text */ --text-primary: #f8fafc; /* Soft White chính thức */
--text-secondary: #cbd5e1; /* Sửa lại xám sáng để nhìn rõ hơn #6b6b6b cũ */
--text-accent: #bce784; /* Lime Cream */ --text-accent: #bce784; /* Lime Cream */
--text-muted: #94a3b8; /* Muted Slate */ --text-muted: #94a3b8; /* Muted Slate */
--text-disabled: #64748b; /* Disabled Text */ --text-disabled: #64748b; /* Disabled Text */
@@ -88,9 +86,19 @@
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3); --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4); --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4);
}
/* Smooth theme transition */ /* FIX LỖI 2: Khai báo ép toàn bộ Input / Textarea trên hệ thống ăn theo màu Theme */
transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease; input, textarea, select {
background-color: var(--surface) !important;
color: var(--text-primary) !important;
border-color: var(--border) !important;
}
/* Đảm bảo chữ gợi ý (placeholder) không bị trùng nền */
input::placeholder, textarea::placeholder {
color: var(--text-muted) !important;
opacity: 0.8;
} }
html, body, #root, .app-container { html, body, #root, .app-container {
@@ -337,6 +345,11 @@
gap: 12px; gap: 12px;
} }
/* Remove padding from child nodes list when folder is collapsed */
.folder-child-content-box:not(.expanded) .child-nodes-list {
padding: 0 !important;
}
/* CSS Grid Accordion Engine - Smooth expand/collapse without layout shattering */ /* CSS Grid Accordion Engine - Smooth expand/collapse without layout shattering */
.stage-accordion-content { .stage-accordion-content {
display: grid !important; display: grid !important;
+8 -8
View File
@@ -962,7 +962,7 @@ const renderInitialsAvatar = (name: string, sizeClass = 'w-10 h-10 text-sm') =>
className={`w-full p-4 hover:bg-slate-900 text-white rounded-2xl flex items-center justify-between font-bold active:scale-98 transition-all border ${ className={`w-full p-4 hover:bg-slate-900 text-white rounded-2xl flex items-center justify-between font-bold active:scale-98 transition-all border ${
activeTab === 'tours' activeTab === 'tours'
? 'bg-indigo-900/40 border-indigo-500/40' ? 'bg-indigo-900/40 border-indigo-500/40'
: 'bg-slate-900/60 border-slate-800/60' : 'bg-slate-850/80 border-slate-700/80'
}`} }`}
> >
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
@@ -978,7 +978,7 @@ const renderInitialsAvatar = (name: string, sizeClass = 'w-10 h-10 text-sm') =>
</div> </div>
</div> </div>
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
<span className="bg-slate-800 px-2.5 py-0.5 text-xs rounded-full text-slate-350 font-bold border border-slate-700"> <span className="bg-slate-800 px-2.5 py-0.5 text-xs rounded-full text-white/90 font-bold border border-slate-700">
{myTours.length} {myTours.length}
</span> </span>
<ChevronRight className="w-4 h-4 text-slate-500" /> <ChevronRight className="w-4 h-4 text-slate-500" />
@@ -990,7 +990,7 @@ const renderInitialsAvatar = (name: string, sizeClass = 'w-10 h-10 text-sm') =>
className={`w-full p-4 hover:bg-slate-900 text-white rounded-2xl flex items-center justify-between font-bold active:scale-98 transition-all border ${ className={`w-full p-4 hover:bg-slate-900 text-white rounded-2xl flex items-center justify-between font-bold active:scale-98 transition-all border ${
activeTab === 'photos' activeTab === 'photos'
? 'bg-indigo-900/40 border-indigo-500/40' ? 'bg-indigo-900/40 border-indigo-500/40'
: 'bg-slate-900/60 border-slate-800/60' : 'bg-slate-850/80 border-slate-700/80'
}`} }`}
> >
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
@@ -1432,7 +1432,7 @@ const renderInitialsAvatar = (name: string, sizeClass = 'w-10 h-10 text-sm') =>
setUnreadTourChats(prev => prev.filter(id => id !== tour.id)); setUnreadTourChats(prev => prev.filter(id => id !== tour.id));
onViewTour(tour.id, 'dashboard'); onViewTour(tour.id, 'dashboard');
}} }}
className="w-full py-2 px-2 bg-indigo-600/20 hover:bg-indigo-600 text-indigo-300 hover:text-white rounded-xl text-xs font-bold transition-all border border-indigo-500/30 hover:border-indigo-500 flex items-center justify-center gap-1 relative whitespace-nowrap" className="w-full py-2 px-2 bg-indigo-600/20 hover:bg-indigo-600 text-black-300 hover:text-white rounded-xl text-xs font-bold transition-all border border-indigo-500/30 hover:border-indigo-500 flex items-center justify-center gap-1 relative whitespace-nowrap"
> >
<MessageSquare className="w-3.5 h-3.5" /> <MessageSquare className="w-3.5 h-3.5" />
<span>Trò chuyện</span> <span>Trò chuyện</span>
@@ -1449,7 +1449,7 @@ const renderInitialsAvatar = (name: string, sizeClass = 'w-10 h-10 text-sm') =>
<button <button
onClick={() => handleTakeCameraPhoto(tour)} onClick={() => handleTakeCameraPhoto(tour)}
disabled={isUploading} disabled={isUploading}
className="flex-1 py-2 px-2 bg-green-600/20 hover:bg-green-600 text-green-300 hover:text-white rounded-xl text-xs font-bold transition-all border border-green-500/30 hover:border-green-500 flex items-center justify-center gap-1 disabled:opacity-50 disabled:cursor-not-allowed" className="flex-1 py-2 px-2 bg-green-600/20 hover:bg-green-600 text-black-300 hover:text-white rounded-xl text-xs font-bold transition-all border border-green-500/30 hover:border-green-500 flex items-center justify-center gap-1 disabled:opacity-50 disabled:cursor-not-allowed"
> >
{isUploading ? ( {isUploading ? (
<Loader2 className="w-3.5 h-3.5 animate-spin" /> <Loader2 className="w-3.5 h-3.5 animate-spin" />
@@ -1461,7 +1461,7 @@ const renderInitialsAvatar = (name: string, sizeClass = 'w-10 h-10 text-sm') =>
<button <button
onClick={() => onViewTour(tour.id, 'dashboard')} onClick={() => onViewTour(tour.id, 'dashboard')}
className="flex-1 py-2 px-2 bg-slate-900 hover:bg-slate-800 text-slate-350 hover:text-white rounded-xl text-xs font-bold transition-all border border-slate-800 hover:border-slate-700 flex items-center justify-center gap-1" className="flex-1 py-2 px-2 bg-slate-900 hover:bg-slate-800 text-slate-850 hover:text-white rounded-xl text-xs font-bold transition-all border border-slate-800 hover:border-slate-700 flex items-center justify-center gap-1"
> >
<span>Chi tiết hành trình</span> <span>Chi tiết hành trình</span>
<ChevronRight className="w-3.5 h-3.5" /> <ChevronRight className="w-3.5 h-3.5" />
@@ -1472,7 +1472,7 @@ const renderInitialsAvatar = (name: string, sizeClass = 'w-10 h-10 text-sm') =>
<button <button
onClick={() => handleEmergencyShare(tour)} onClick={() => handleEmergencyShare(tour)}
disabled={loadingShare} disabled={loadingShare}
className="w-full py-2 px-3 bg-rose-600/10 hover:bg-rose-600 text-rose-400 hover:text-white rounded-xl text-xs font-bold transition-all border border-rose-500/20 hover:border-rose-500 flex items-center justify-center gap-1.5 disabled:opacity-50 disabled:cursor-not-allowed" className="w-full py-2 px-3 bg-rose-600/10 hover:bg-rose-600 text-rose-400 hover:text-white-500 rounded-xl text-xs font-bold transition-all border border-rose-500/20 hover:border-rose-500 flex items-center justify-center gap-1.5 disabled:opacity-50 disabled:cursor-not-allowed"
> >
{loadingShare ? ( {loadingShare ? (
<Loader2 className="w-3.5 h-3.5 animate-spin" /> <Loader2 className="w-3.5 h-3.5 animate-spin" />
@@ -1621,7 +1621,7 @@ const renderInitialsAvatar = (name: string, sizeClass = 'w-10 h-10 text-sm') =>
setMobileShowDetail(true); setMobileShowDetail(true);
} }
}} }}
className="p-1.5 bg-indigo-950/50 hover:bg-indigo-600 text-indigo-300 hover:text-white border border-indigo-800/40 hover:border-indigo-500 rounded-lg text-xs font-bold transition-all" className="p-1.5 bg-indigo-950/550 hover:bg-indigo-600 text-blue-500 hover:text-white border border-indigo-800/40 hover:border-indigo-500 rounded-lg text-xs font-bold transition-all"
title="Trò chuyện" title="Trò chuyện"
> >
<MessageSquare className="w-3.5 h-3.5" /> <MessageSquare className="w-3.5 h-3.5" />
+3 -3
View File
@@ -2898,7 +2898,7 @@ export const TourDetailPage = ({
value={adultCountInput} value={adultCountInput}
onChange={(e) => setAdultCountInput(Number(e.target.value))} onChange={(e) => setAdultCountInput(Number(e.target.value))}
min="0" min="0"
className="w-full px-4 py-2 border border-gray-200 rounded-xl focus:ring-blue-500 focus:border-blue-500" className="w-full px-4 py-2 border border-yotripLight-khaki rounded-xl focus:ring-yotripLight-text focus:border-yotripLight-text bg-white text-yotripLight-text dark:bg-yotripDark-surface dark:text-white dark:border-yotripDark-surface-muted dark:focus:ring-yotripDark-lime dark:focus:border-yotripDark-lime transition-colors duration-200"
/> />
</div> </div>
<div> <div>
@@ -2909,7 +2909,7 @@ export const TourDetailPage = ({
value={childCountInput} value={childCountInput}
onChange={(e) => setChildCountInput(Number(e.target.value))} onChange={(e) => setChildCountInput(Number(e.target.value))}
min="0" min="0"
className="w-full px-4 py-2 border border-gray-200 rounded-xl focus:ring-blue-500 focus:border-blue-500" className="w-full px-4 py-2 border border-yotripLight-khaki rounded-xl focus:ring-yotripLight-text focus:border-yotripLight-text bg-white text-yotripLight-text dark:bg-yotripDark-surface dark:text-white dark:border-yotripDark-surface-muted dark:focus:ring-yotripDark-lime dark:focus:border-yotripDark-lime transition-colors duration-200"
/> />
</div> </div>
<div> <div>
@@ -2921,7 +2921,7 @@ export const TourDetailPage = ({
onChange={(e) => setChildDiscountInput(Number(e.target.value))} onChange={(e) => setChildDiscountInput(Number(e.target.value))}
min="0" min="0"
max="100" max="100"
className="w-full px-4 py-2 border border-gray-200 rounded-xl focus:ring-blue-500 focus:border-blue-500" className="w-full px-4 py-2 border border-yotripLight-khaki rounded-xl focus:ring-yotripLight-text focus:border-yotripLight-text bg-white text-yotripLight-text dark:bg-yotripDark-surface dark:text-white dark:border-yotripDark-surface-muted dark:focus:ring-yotripDark-lime dark:focus:border-yotripDark-lime transition-colors duration-200"
/> />
</div> </div>
</div> </div>