Skip to content

Commit 05e77db

Browse files
authored
Merge pull request #35 from SyncfusionExamples/999933-Employee-Management
999933: resolved bugs and UI issues
2 parents e0c768f + d21e0a7 commit 05e77db

File tree

10 files changed

+328
-44
lines changed

10 files changed

+328
-44
lines changed

Employee_Managment_App/src/App.css

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
/* 1. GENERAL: Container paddings shrink, stacking, font adapt for mobile */
2+
@media (max-width: 768px) {
3+
.app-layout {
4+
padding-left: 0 !important;
5+
padding-right: 0 !important;
6+
min-width: 0;
7+
font-size: 15px;
8+
}
9+
.app-main {
10+
padding: 6px 0 0 0 !important;
11+
}
12+
.achievements-container,
13+
.policies-content,
14+
.employees-content {
15+
padding: 10px 5px !important;
16+
}
17+
}
18+
19+
/* 2. SIDEBAR: overlay, hide, and usability tweaks for mobile */
20+
@media (max-width: 991px) {
21+
.e-sidebar {
22+
width: 80vw !important;
23+
min-width: 200px !important;
24+
max-width: 97vw !important;
25+
left: 0 !important;
26+
top: 0 !important;
27+
height: 100vh !important;
28+
border-radius: 0 !important;
29+
box-shadow: 0 2px 24px rgba(0,0,0,0.22);
30+
z-index: 1111;
31+
}
32+
.app-sidebar {
33+
min-width: 0;
34+
width: 100% !important;
35+
padding: 0 !important;
36+
}
37+
.sidebar-brand {
38+
gap: 8px !important;
39+
font-size: 19px;
40+
padding: 8px 0 9px 12px !important;
41+
}
42+
.sidebar-toggle {
43+
margin-left: auto;
44+
}
45+
.nav.flex-column {
46+
gap: 0;
47+
padding: 2px 0;
48+
}
49+
}
50+
51+
/* 3. TOP NAV: squash items, stack user info, hide create if needed */
52+
@media (max-width: 768px) {
53+
.topnav-inner {
54+
gap: 3px !important;
55+
padding: 0 4px !important;
56+
}
57+
.cluster-right {
58+
gap: 3px !important;
59+
}
60+
.btn-create-group, .btn-create {
61+
min-width: 70px !important;
62+
padding: 0 7px;
63+
font-size: 13px !important;
64+
}
65+
.topnav-avatar-name {
66+
font-size: 12px;
67+
margin-left: 4px !important;
68+
word-break: break-all;
69+
}
70+
}
71+
72+
/* 4. SEARCH: search bar fills width, form controls height shrink */
73+
@media (max-width: 768px) {
74+
.cluster-center, .search-form {
75+
width: 97vw !important;
76+
min-width: 0 !important;
77+
max-width: 99vw !important;
78+
}
79+
.search-form .search-field {
80+
height: 32px !important;
81+
font-size: 14px;
82+
}
83+
}
84+
/* Mobile search field needs full width */
85+
@media (max-width: 530px) {
86+
.search-form,
87+
.search-field.input-group {
88+
width: 99vw !important;
89+
min-width: 0 !important;
90+
max-width: 100vw !important;
91+
}
92+
}
93+
94+
/* 5. BUTTONS, CHIPS, and TOOLBARS: stack and compress */
95+
@media (max-width: 640px) {
96+
.toolbar-right,
97+
.org-filters__pills,
98+
.filter-chip-row {
99+
flex-wrap: wrap !important;
100+
gap: 7px !important;
101+
row-gap: 6px !important;
102+
justify-content: flex-start !important;
103+
}
104+
.toolbar-field, .filter-chip {
105+
font-size: 13px !important;
106+
padding: 6px 10px !important;
107+
}
108+
.annc-panel-tabs button {
109+
padding: 8px 4px !important;
110+
}
111+
}
112+
113+
/* 6. GRIDS/TABLES: Horizontal scroll for overflow columns on mobile */
114+
@media (max-width: 900px) {
115+
.e-grid, .lb-sections, .policies-grid-wrapper .e-grid {
116+
overflow-x: auto !important;
117+
min-width: 360px !important;
118+
width: 100vw !important;
119+
}
120+
}
121+
/* For actual grid row cells, allow wrapping */
122+
@media (max-width: 640px) {
123+
.e-grid .e-rowcell, .lb-row, .policy-name-cell {
124+
font-size: 13px !important;
125+
padding-left: 4px !important;
126+
padding-right: 4px !important;
127+
white-space: normal !important;
128+
}
129+
}
130+
/* Keep action buttons visible in grid on small screens */
131+
@media (max-width: 640px) {
132+
.policy-dialog, .e-dialog {
133+
max-width: 97vw !important;
134+
min-width: 0 !important;
135+
}
136+
}
137+
138+
/* 7. EMPLOYEE PROFILE (tabs, avatar, flexing) */
139+
@media (max-width: 600px) {
140+
.overview-header {
141+
flex-direction: column !important;
142+
align-items: flex-start !important;
143+
gap: 3px !important;
144+
}
145+
.profile-data-name, .profile-data-mail, .profile-data-designation, .profile-data-supervisor, .profile-data-branch {
146+
font-size: 14px !important;
147+
}
148+
.profile-image svg {
149+
width: 48px !important;
150+
height: 48px !important;
151+
}
152+
}
153+
154+
/* 8. DIALOGS/ANNOUNCEMENTS: Center and fill for mobile */
155+
@media (max-width: 570px) {
156+
.e-annc-detail-dialog.e-dialog, .policy-dialog.e-dialog {
157+
width: 97vw !important;
158+
max-width: 97vw !important;
159+
left: 1vw !important;
160+
right: 1vw !important;
161+
min-width: 0 !important;
162+
border-radius: 11px !important;
163+
padding-left: 0 !important;
164+
padding-right: 0 !important;
165+
}
166+
.annc-dlg-content {
167+
padding-left: 2vw !important;
168+
padding-right: 2vw !important;
169+
}
170+
}
171+
172+
/* 9. ANNOUNCEMENTS PANEL: right panel covers full width on tiny screens */
173+
@media (max-width: 480px) {
174+
.annc-right-panel {
175+
width: 99vw !important;
176+
min-width: 0 !important;
177+
left: 0 !important;
178+
border-radius: 0 !important;
179+
max-width: 100vw !important;
180+
font-size: 14px !important;
181+
}
182+
.annc-panel-header, .annc-panel-tabs, .annc-panel-content {
183+
padding-left: 8px !important;
184+
padding-right: 8px !important;
185+
}
186+
}
187+
188+
/* 10. LEADERBOARD/ACHIEVEMENTS: Stacked layout for sections on mobile */
189+
@media (max-width: 640px) {
190+
.lb-sections {
191+
grid-template-columns: 1fr !important;
192+
}
193+
.lb-section {
194+
min-width: 0 !important;
195+
border-radius: 10px !important;
196+
margin-bottom: 14px !important;
197+
}
198+
}
199+
200+
/* 11. GENERAL: Shrink font slightly on XS mobile, compress app-body paddings */
201+
@media (max-width: 420px) {
202+
html, body {
203+
font-size: 13.6px !important;
204+
}
205+
.app-layout {
206+
padding: 0 0 !important;
207+
}
208+
}
209+
210+
@media (max-width: 991px) {
211+
.e-sidebar {
212+
width: 68vw !important;
213+
font-size: 30px;
214+
min-width: 160px !important;
215+
max-width: 88vw !important;
216+
border-top-right-radius: 20px;
217+
border-bottom-right-radius: 20px;
218+
box-shadow: 3px 0 10px rgba(0,0,0,0.34);
219+
background: #222b3c;
220+
}
221+
.nav-icon{
222+
font-size:30px !important;
223+
margin-right:15px;
224+
}
225+
.sidebar-brand{
226+
font-size: 35px;
227+
}
228+
.title{
229+
font-size: 35px !important;
230+
}
231+
.nav .flex-column{
232+
margin-top: 15px;
233+
}
234+
.sidebar-toggle{
235+
margin-right: 10px !important;
236+
}
237+
}

Employee_Managment_App/src/App.tsx

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,13 @@ function App() {
140140
onSearch={(q) => console.log('Search:', q)}
141141
onMarkRead={handleMarkRead}
142142
onMarkAllRead={handleMarkAllRead}
143+
onOpenSidebar={() => {
144+
if (isDesktop) {
145+
setSidebarCollapsed(false);
146+
} else {
147+
setMobileSidebarOpen(true);
148+
}
149+
}}
143150
/>
144151

145152
{/* Syncfusion Sidebar */}
@@ -167,59 +174,39 @@ function App() {
167174
<div className="title">{collapsed ? 'HR' : 'HR Portal'}</div>
168175
<button
169176
type="button"
170-
className="sidebar-toggle"
177+
className="sidebar-toggle e-icons e-menu"
171178
aria-label={collapsed ? 'Expand menu' : 'Collapse menu'}
172179
title={collapsed ? 'Expand' : 'Collapse'}
173180
onClick={isDesktop ? toggleDesktopSidebar : toggleMobileSidebar}
174181
>
175-
{/* menu icon */}
176-
<svg width="18" height="18" viewBox="0 0 24 24" aria-hidden="true">
177-
<path fill="currentColor" d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z" />
178-
</svg>
179182
</button>
180183
</div>
181184

182185
<ul className="nav flex-column">
183186
<li className="nav-item">
184187
<NavLink className="nav-link" to="/" end>
185-
<span className="nav-icon" aria-hidden="true">
186-
{/* user/profile */}
187-
<svg width="18" height="18" viewBox="0 0 24 24">
188-
<path fill="currentColor" d="M12 12a5 5 0 1 0-5-5a5 5 0 0 0 5 5zm0 2c-4.418 0-8 2.239-8 5v1h16v-1c0-2.761-3.582-5-8-5z" />
189-
</svg>
188+
<span className="nav-icon e-icons e-user" aria-hidden="true">
190189
</span>
191190
{!collapsed && <span className="nav-text">My Profile</span>}
192191
</NavLink>
193192
</li>
194193
<li className="nav-item">
195194
<NavLink className="nav-link" to="/organization">
196-
<span className="nav-icon" aria-hidden="true">
197-
{/* organization/people */}
198-
<svg width="18" height="18" viewBox="0 0 24 24">
199-
<path fill="currentColor" d="M16 11a4 4 0 1 0-3.465-2H11V7H8V5H4v2H1v3h3v2h3v2h3v2h3.535A4 4 0 1 0 16 11zM6 7h2v2H6zm10-2a2 2 0 1 1 0 4a2 2 0 0 1 0-4zm0 10a2 2 0 1 1 0 4a2 2 0 0 1 0-4z" />
200-
</svg>
195+
<span className="nav-icon e-icons e-xml-mapping" aria-hidden="true">
201196
</span>
202197
{!collapsed && <span className="nav-text">Organization</span>}
203198
</NavLink>
204199
</li>
205200
<li className="nav-item">
206201
<NavLink className="nav-link" to="/policies">
207-
<span className="nav-icon" aria-hidden="true">
208-
{/* policy/document */}
209-
<svg width="18" height="18" viewBox="0 0 24 24">
210-
<path fill="currentColor" d="M6 2h9l5 5v15H6zM8 4v16h10V9h-5V4zm2 7h6v2h-6zm0 4h6v2h-6z" />
211-
</svg>
202+
<span className="nav-icon e-icons e-file-format" aria-hidden="true">
212203
</span>
213204
{!collapsed && <span className="nav-text">Policies</span>}
214205
</NavLink>
215206
</li>
216207
<li className="nav-item">
217208
<NavLink className="nav-link" to="/achievements">
218-
<span className="nav-icon" aria-hidden="true">
219-
{/* trophy */}
220-
<svg width="18" height="18" viewBox="0 0 24 24">
221-
<path fill="currentColor" d="M17 3H7v4a5 5 0 0 0 4 4.9V14H8v2h8v-2h-3v-2.1A5 5 0 0 0 17 7zM7 7V5h10v2a3 3 0 0 1-6 0H9a3 3 0 0 1-2 3z" />
222-
</svg>
209+
<span className="nav-icon e-icons e-activities" aria-hidden="true">
223210
</span>
224211
{!collapsed && <span className="nav-text">Achievements</span>}
225212
</NavLink>

Employee_Managment_App/src/components/Achievements.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ const Achievements: React.FC<AchievementsProps> = ({ userInfo, onlyTeamIfUser =
272272
<div className="lb-sections">
273273
<section className="lb-section">
274274
<header className="lb-header bg-r-overall">
275-
<div className="lb-header-icon icon-overall e-icons e-user" aria-hidden>
275+
<div className="lb-header-icon icon-overall e-icons e-people" aria-hidden>
276276
</div>
277277
<div className="lb-header-text">
278278
<div className="lb-title">Overall</div>

Employee_Managment_App/src/components/Announcement.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,14 @@
146146
position: relative;
147147
}
148148
.annc-panel-item.is-unread {
149+
margin-bottom: 5px;
150+
padding: 6px;
149151
background: #f0fdf9;
150152
border-color: #d1fae5;
151153
}
152154
.annc-panel-item.is-read {
155+
margin-bottom: 5px;
156+
padding: 6px;
153157
opacity: 0.75;
154158
}
155159
.annc-panel-item:hover {

Employee_Managment_App/src/components/Announcement.tsx

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,34 @@ export const AnnouncementPanel: React.FC<AnnouncementPanelProps> = ({
6262
React.useEffect(() => {
6363
const handleDocClick = (ev: MouseEvent) => {
6464
if (!open) return;
65-
if (panelRef.current && !panelRef.current.contains(ev.target as Node)) onClose();
65+
66+
const target = ev.target as Node;
67+
68+
// If detail dialog is open, ignore clicks inside dialog or its overlay
69+
if (detailOpen) {
70+
const dialogEl = document.querySelector('.e-annc-detail-dialog') as HTMLElement | null;
71+
const overlayEl = document.querySelector('.e-dlg-overlay') as HTMLElement | null;
72+
73+
const clickedInsideDialog =
74+
(dialogEl && dialogEl.contains(target)) ||
75+
(overlayEl && overlayEl.contains(target));
76+
77+
if (clickedInsideDialog) {
78+
// Let the dialog handle its own close via overlayClick; don't close the aside
79+
return;
80+
}
81+
}
82+
83+
// Close aside only when clicking outside both the aside and (if open) the dialog
84+
if (panelRef.current && !panelRef.current.contains(target)) {
85+
onClose();
86+
}
6687
};
67-
document.addEventListener('click', handleDocClick);
68-
return () => document.removeEventListener('click', handleDocClick);
69-
}, [open, onClose]);
88+
89+
// Use capture to catch the click before Syncfusion might stop propagation
90+
document.addEventListener('click', handleDocClick, true);
91+
return () => document.removeEventListener('click', handleDocClick, true);
92+
}, [open, onClose, detailOpen]);
7093

7194
const setActiveTab = (t: 'notifications' | 'announcements') => {
7295
setTab(t);

Employee_Managment_App/src/components/AnnouncementDialog.css

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,9 @@
7979
}
8080

8181
.annc-dlg-details {
82-
display: grid;
83-
grid-template-columns: repeat(3, minmax(180px, 1fr));
84-
gap: 12px 18px;
82+
display: flex;
83+
justify-content: space-between;
84+
align-items: center;
8585
}
8686
@media (max-width: 920px) {
8787
.annc-dlg-details { grid-template-columns: repeat(2, minmax(180px, 1fr)); }

0 commit comments

Comments
 (0)