Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 59 additions & 1 deletion Employee_Managment_App/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// src/App.tsx
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useMemo } from 'react';
import { BrowserRouter as Router, Routes, Route, NavLink } from 'react-router-dom';
import './App.css';
import TopNav from './components/TopNav';
Expand All @@ -8,6 +8,7 @@ import Policies from './components/Policies';
import Achievements from './components/Achievements';
import Organization from './components/Organization';
import EmployeeInfo from './components/EmployeeInfo';
import { PanelItem } from './components/Announcement';

// Syncfusion Sidebar
import { SidebarComponent } from '@syncfusion/ej2-react-navigations';
Expand Down Expand Up @@ -45,11 +46,62 @@ function App() {
const [sidebarCollapsed, setSidebarCollapsed] = useState(false); // desktop dock
const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false); // mobile overlay
const isDesktop = useMediaQuery('(min-width: 992px)');

// Notification items with read status
const [notificationItems, setNotificationItems] = useState<PanelItem[]>([
{ id: 1, title: 'Interview for Customer Support Specialist', subtitle: 'Announcement', date: 'Sep 18', type: 'notification', content: 'You are invited for the Customer Support Specialist interview on Sep 22 at 11:00 AM. Please bring your updated resume and ID.', read: false },
{ id: 2, title: 'Interview for Facilities Executive', subtitle: 'Announcement', date: 'Sep 9', type: 'notification', content: 'Facilities Executive interview is scheduled for Sep 23 at 2:30 PM in Meeting Room A.', read: false },
{ id: 3, title: 'Interview for Office Coordinator / Admin', subtitle: 'Announcement', date: 'Sep 5', type: 'notification', content: 'Your interview for the Office Coordinator / Admin position is scheduled on Sep 25 at 10:00 AM in Conference Room B. Please bring your updated resume and a government-issued ID.', read: false },
]);

const [announcementItems, setAnnouncementItems] = useState<PanelItem[]>([
{ id: 'a1', title: 'Policy Update: Remote Work Guidelines', subtitle: 'Corporate Communication', date: 'Sep 16', type: 'announcement', content: 'We have updated our Remote Work Guidelines effective Oct 1. Key changes include flexible core hours and equipment reimbursement policy. Please read the full policy on the intranet.', read: false },
{ id: 'a2', title: 'Holiday: Office Closed on 2nd Oct', subtitle: 'HR', date: 'Sep 14', type: 'announcement', content: 'In observance of a public holiday, all offices will remain closed on 2nd October. Normal operations resume on 3rd October.', read: false },
{ id: 'a3', title: 'Quarterly Town Hall this Friday', subtitle: 'Admin', date: 'Sep 12', type: 'announcement', content: 'Join us for the Quarterly Town Hall on Sep 20 at 4:00 PM in the Main Auditorium. Leadership will share company updates, upcoming initiatives, and answer your questions. Attendance is encouraged.', read: false },
]);

useEffect(() => {
if (isDesktop) setMobileSidebarOpen(false);
}, [isDesktop]);

// Calculate unread counts
const notifications = useMemo(() => ({
bell: 3,
chat: notificationItems.filter(item => !item.read).length,
tasks: 1,
announcements: announcementItems.filter(item => !item.read).length,
}), [notificationItems, announcementItems]);

// Handler to mark a single item as read
const handleMarkRead = (itemId: string | number, isNotification: boolean) => {
if (isNotification) {
setNotificationItems((prev) =>
prev.map((item) =>
item.id === itemId ? { ...item, read: true } : item
)
);
} else {
setAnnouncementItems((prev) =>
prev.map((item) =>
item.id === itemId ? { ...item, read: true } : item
)
);
}
};

// Handler to mark all as read
const handleMarkAllRead = (tab: 'notifications' | 'announcements') => {
if (tab === 'notifications') {
setNotificationItems((prev) =>
prev.map((item) => ({ ...item, read: true }))
);
} else {
setAnnouncementItems((prev) =>
prev.map((item) => ({ ...item, read: true }))
);
}
};

const layoutVars: LayoutCSSVars = {
'--sidebar-expanded': `${SIDEBAR_WIDTH}px`,
'--sidebar-collapsed': `${SIDEBAR_WIDTH_COLLAPSED}px`,
Expand Down Expand Up @@ -82,14 +134,20 @@ function App() {
companyName="NexGen7 Software"
userFullName="Test Person"
headerOffsetLeft={isDesktop ? (sidebarCollapsed ? SIDEBAR_WIDTH_COLLAPSED : SIDEBAR_WIDTH) : 0}
notifications={notifications}
notificationItems={notificationItems}
announcementItems={announcementItems}
onSearch={(q) => console.log('Search:', q)}
onMarkRead={handleMarkRead}
onMarkAllRead={handleMarkAllRead}
/>

{/* Syncfusion Sidebar */}
<SidebarComponent
width={`${SIDEBAR_WIDTH}px`}
dockSize={`${SIDEBAR_WIDTH_COLLAPSED}px`}
enableDock={sbEnableDock}
enableGestures={false}
isOpen={sbIsOpen}
type={sbType as any}
position="Left"
Expand Down
24 changes: 12 additions & 12 deletions Employee_Managment_App/src/components/Achievements.css
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ body,
/* removed decorative radial gradients */
min-height: 100%;
color: var(--text);
font-family: Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji";
}
font-family: 'Roboto', sans-serif;
}

/* Toolbar - flat */
.achievements-toolbar {
Expand Down Expand Up @@ -70,14 +70,17 @@ body,
}

.toolbar-field {
display: grid;
display: flex;
justify-content: center;
align-items: center;
gap: 6px;
font-size: 12px;
color: var(--muted);
}

.field-label {
opacity: .9;
font-size: 14px;
}

/* Syncfusion dropdowns */
Expand Down Expand Up @@ -144,7 +147,7 @@ body,
.lb-section {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 10px;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
overflow: hidden;
}

Expand All @@ -153,6 +156,7 @@ body,
display: flex;
align-items: center;
gap: 10px;
height: 70px;
padding: 10px 12px;
border-bottom: 1px solid var(--border);
background: #fff;
Expand All @@ -171,18 +175,21 @@ body,
.bg-r-overall {
background: #fb5757;
color: #fff;
font-size: 22px;
}

.icon-task,
.bg-r-task {
background: #d65e22;
color: #fff;
font-size: 22px;
}

.icon-att,
.bg-r-attendance {
background: #317701;
color: #fff;
font-size: 22px;
}

.lb-header-text {
Expand All @@ -196,7 +203,7 @@ body,
}

.lb-sub {
font-size: 10px;
font-size: 14px;
color: #fff;
letter-spacing: 1px;
padding-top: 5px;
Expand Down Expand Up @@ -292,13 +299,6 @@ body,
font-size: 13px;
letter-spacing: .2px;
font-feature-settings: "tnum" on, "lnum" on;
background: #f8fafc;
padding: 4px 8px;
border-radius: 6px;
border: 1px solid #e5e7eb;
font-family: 'Roboto', sans-serif;
}

.score.flat {
background: #f8fafc;
}
21 changes: 7 additions & 14 deletions Employee_Managment_App/src/components/Achievements.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,14 +209,14 @@ const Achievements: React.FC<AchievementsProps> = ({ userInfo, onlyTeamIfUser =

<div className="toolbar-right">
<label className="toolbar-field">
<span className="field-label">Role</span>
<span className="field-label" >Role</span>
<DropDownListComponent
id="role-ddl"
cssClass="sf-field-input"
dataSource={roles}
fields={{ text: 'text', value: 'value' }}
value={role}
width="180px"
width="135px"
placeholder="Select role"
change={(e: any) => setRole(e.value)}
aria-label="Filter by role"
Expand All @@ -231,6 +231,7 @@ const Achievements: React.FC<AchievementsProps> = ({ userInfo, onlyTeamIfUser =
id="month-ddl"
cssClass="sf-field-input"
dataSource={months}
width="100px"
fields={{ text: 'text', value: 'value' }}
value={month}
placeholder="Select month"
Expand All @@ -247,6 +248,7 @@ const Achievements: React.FC<AchievementsProps> = ({ userInfo, onlyTeamIfUser =
id="year-ddl"
cssClass="sf-field-input"
dataSource={years}
width="100px"
fields={{ text: 'text', value: 'value' }}
value={year}
placeholder="Select year"
Expand All @@ -270,10 +272,7 @@ const Achievements: React.FC<AchievementsProps> = ({ userInfo, onlyTeamIfUser =
<div className="lb-sections">
<section className="lb-section">
<header className="lb-header bg-r-overall">
<div className="lb-header-icon icon-overall" aria-hidden>
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
<path d="M7 10a2 2 0 1 1 0-4 2 2 0 0 1 0 4zm10 0a2 2 0 1 1 0-4 2 2 0 0 1 0 4zM12 9a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm-7 8v-1a4 4 0 0 1 4-4h2a4 4 0 0 1 4 4v1H5zm10 0v-1a5 5 0 0 1 5-5h.5A1.5 1.5 0 0 1 22 12.5V17H15z" />
</svg>
<div className="lb-header-icon icon-overall e-icons e-user" aria-hidden>
</div>
<div className="lb-header-text">
<div className="lb-title">Overall</div>
Expand All @@ -297,10 +296,7 @@ const Achievements: React.FC<AchievementsProps> = ({ userInfo, onlyTeamIfUser =

<section className="lb-section">
<header className="lb-header bg-r-task">
<div className="lb-header-icon icon-task" aria-hidden>
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
<path d="M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" />
</svg>
<div className="lb-header-icon icon-task e-icons e-check-tick" aria-hidden>
</div>
<div className="lb-header-text">
<div className="lb-title">Task</div>
Expand All @@ -324,10 +320,7 @@ const Achievements: React.FC<AchievementsProps> = ({ userInfo, onlyTeamIfUser =

<section className="lb-section">
<header className="lb-header bg-r-attendance">
<div className="lb-header-icon icon-att" aria-hidden>
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
<path d="M19 3h-1V1h-2v2H8V1H6v2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2zm0 16H5V8h14v11z" />
</svg>
<div className="lb-header-icon icon-att e-icons e-day" aria-hidden>
</div>
<div className="lb-header-text">
<div className="lb-title">Attendance</div>
Expand Down
32 changes: 30 additions & 2 deletions Employee_Managment_App/src/components/Announcement.css
Original file line number Diff line number Diff line change
Expand Up @@ -137,17 +137,37 @@
}
.annc-panel-item {
display: grid;
grid-template-columns: 36px 1fr;
grid-template-columns: 36px 1fr 20px;
gap: 10px;
padding: 10px 8px;
border-radius: 12px;
border: 1px solid transparent;
transition: background 160ms ease, border-color 160ms ease;
transition: background 160ms ease, border-color 160ms ease, opacity 160ms ease;
position: relative;
}
.annc-panel-item.is-unread {
background: #f0fdf9;
border-color: #d1fae5;
}
.annc-panel-item.is-read {
opacity: 0.75;
}
.annc-panel-item:hover {
background: #f8fffb;
border-color: #e8f7f1;
}
.annc-panel-item.is-unread:hover {
background: #ecfdf5;
}
.unread-indicator {
width: 8px;
height: 8px;
background: var(--annc-theme);
border-radius: 50%;
align-self: center;
justify-self: end;
margin-right: 4px;
}
.annc-item-icon {
width: 36px;
height: 36px;
Expand All @@ -169,6 +189,14 @@
text-overflow: ellipsis;
white-space: nowrap;
}
.annc-item-title.unread {
font-weight: 700;
color: var(--annc-text);
}
.annc-item-title.read {
font-weight: 500;
color: #94a3b8;
}
.annc-item-meta {
margin-top: 2px;
font-size: 12px;
Expand Down
Loading