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
357 changes: 132 additions & 225 deletions ichub-frontend/src/App.css

Large diffs are not rendered by default.

240 changes: 173 additions & 67 deletions ichub-frontend/src/components/general/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,83 +21,189 @@
********************************************************************************/

import { useState } from 'react';
import { MainNavigation, IconButton } from '@catena-x/portal-shared-components';
import PersonIcon from '@mui/icons-material/Person';
import { Menu, MenuItem, Typography, Divider, ListItemIcon } from '@mui/material';
import AccountCircleIcon from '@mui/icons-material/AccountCircle';
import SettingsIcon from '@mui/icons-material/Settings';
import LogoutIcon from '@mui/icons-material/Logout';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import IconButton from '@mui/material/IconButton';
import Badge from '@mui/material/Badge';
import MenuItem from '@mui/material/MenuItem';
import Menu from '@mui/material/Menu';
import AccountCircle from '@mui/icons-material/AccountCircle';
import MailIcon from '@mui/icons-material/Mail';
import NotificationsIcon from '@mui/icons-material/Notifications';
import MoreIcon from '@mui/icons-material/MoreVert';
import { Divider, ListItemIcon, Typography } from '@mui/material';
import { Logout, Settings } from '@mui/icons-material';

const Header = () => {
const [anchorEl, setAnchorEl] = useState(null);
const open = Boolean(anchorEl);
export default function PrimarySearchAppBar() {
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [mobileMoreAnchorEl, setMobileMoreAnchorEl] = useState<null | HTMLElement>(null);

const handleMenuOpen = (event) => {
const isMenuOpen = Boolean(anchorEl);
const isMobileMenuOpen = Boolean(mobileMoreAnchorEl);

const handleProfileMenuOpen = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
};

const handleMobileMenuClose = () => {
setMobileMoreAnchorEl(null);
};

const handleMenuClose = () => {
setAnchorEl(null);
handleMobileMenuClose();
};

return (
<MainNavigation
items={[
{ href: '/', title: 'Industry Core Hub' },
]}
>
<div className='main-logo-wrapper'>
<a href="/" className="main-logo-link">
<img
src="/241117_Tractus_X_Logo_RGB_Light_Version.png"
alt="Eclipse Tractus-X logo"
className='main-logo'
/>
</a>
</div>
<div>
<IconButton aria-label="user-menu" onClick={handleMenuOpen}>
<PersonIcon />
</IconButton>
<Menu
anchorEl={anchorEl}
open={open}
onClose={handleMenuClose}
className='navbar-user-dropdown'
>
{/* Encabezado con nombre y email */}
<Typography variant="subtitle1" sx={{ padding: '8px 16px 0px 16px', fontWeight: 'bold' }}>
const handleMobileMenuOpen = (event: React.MouseEvent<HTMLElement>) => {
setMobileMoreAnchorEl(event.currentTarget);
};

const menuId = 'primary-search-account-menu';
const renderMenu = (
<Menu
anchorEl={anchorEl}
id={menuId}
open={isMenuOpen}
onClose={handleMenuClose}
>
<Typography variant="subtitle1" sx={{ padding: '8px 16px 0px 16px', fontWeight: 'bold' }}>
Mathias Brunkow Moser
</Typography>
<Typography variant="body2" color="text.secondary" sx={{ padding: '0 16px 8px', fontStyle: 'italic' }}>
CX-Operator
</Typography>
<Divider />
</Typography>
<Typography variant="body2" color="text.secondary" sx={{ padding: '0 16px 8px', fontStyle: 'italic' }}>
CX-Operator
</Typography>
<Divider />

{/* Opciones del menú */}
<MenuItem onClick={handleMenuClose}>
<ListItemIcon>
<AccountCircleIcon fontSize="small" />
</ListItemIcon>
Profile
</MenuItem>
<MenuItem onClick={handleMenuClose}>
<ListItemIcon>
<SettingsIcon fontSize="small" />
</ListItemIcon>
Settings
</MenuItem>
<Divider />
<MenuItem onClick={handleMenuClose}>
<ListItemIcon>
<LogoutIcon fontSize="small" />
</ListItemIcon>
Logout
</MenuItem>
</Menu>
</div>
</MainNavigation>
{/* Opciones del menú */}
<MenuItem onClick={handleMenuClose}>
<ListItemIcon>
<AccountCircle fontSize="small" />
</ListItemIcon>
Profile
</MenuItem>
<MenuItem onClick={handleMenuClose}>
<ListItemIcon>
<Settings fontSize="small" />
</ListItemIcon>
Settings
</MenuItem>
<Divider />
<MenuItem onClick={handleMenuClose}>
<ListItemIcon>
<Logout fontSize="small" />
</ListItemIcon>
Logout
</MenuItem>
</Menu>
);
};

export default Header;
const mobileMenuId = 'primary-search-account-menu-mobile';
const renderMobileMenu = (
<Menu
anchorEl={mobileMoreAnchorEl}
anchorOrigin={{
vertical: 'top',
horizontal: 'right',
}}
id={mobileMenuId}
keepMounted
transformOrigin={{
vertical: 'top',
horizontal: 'right',
}}
open={isMobileMenuOpen}
onClose={handleMobileMenuClose}
>
<MenuItem>
<IconButton size="large" aria-label="show 4 new mails">
<Badge badgeContent={4} color="error">
<MailIcon />
</Badge>
</IconButton>
<p>Messages</p>
</MenuItem>
<MenuItem>
<IconButton
size="large"
aria-label="show 17 new notifications"
>
<Badge badgeContent={17} color="error">
<NotificationsIcon />
</Badge>
</IconButton>
<p>Notifications</p>
</MenuItem>
<MenuItem onClick={handleProfileMenuOpen}>
<IconButton
size="large"
aria-label="account of current user"
aria-controls="primary-search-account-menu"
aria-haspopup="true"
>
<AccountCircle />
</IconButton>
<p>Profile</p>
</MenuItem>
</Menu>
);

return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static" className='ichub-header'>
<Toolbar>
<a href="/">
<img
src="/241117_Tractus_X_Logo_RGB_Light_Version.png"
alt="Eclipse Tractus-X logo"
className='main-logo'
/>
</a>
<Box sx={{ flexGrow: 1, display: 'flex', justifyContent: 'center' }}>
<h2>Industry Core Hub</h2>
</Box>
<Box sx={{ display: { xs: 'none', md: 'flex' } }}>
<IconButton size="large" aria-label="show 4 new mails">
<Badge badgeContent={4} color="error">
<MailIcon />
</Badge>
</IconButton>
<IconButton
size="large"
aria-label="show 17 new notifications"
>
<Badge badgeContent={17} color="error">
<NotificationsIcon />
</Badge>
</IconButton>
<IconButton
size="large"
edge="end"
aria-label="account of current user"
aria-controls={menuId}
aria-haspopup="true"
onClick={handleProfileMenuOpen}
className='user-button'
>
<AccountCircle />
</IconButton>
</Box>
<Box sx={{ display: { xs: 'flex', md: 'none' } }}>
<IconButton
size="large"
aria-label="show more"
aria-controls={mobileMenuId}
aria-haspopup="true"
onClick={handleMobileMenuOpen}
color="inherit"
>
<MoreIcon />
</IconButton>
</Box>
</Toolbar>
</AppBar>
{renderMobileMenu}
{renderMenu}
</Box>
);
}
41 changes: 41 additions & 0 deletions ichub-frontend/src/components/general/PageNotification.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/********************************************************************************
* Eclipse Tractus-X - Industry Core Hub Frontend
*
* Copyright (c) 2025 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the
* License for the specific language govern in permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/


import { Grid2 } from '@mui/material';
import { PageNotifications } from '@catena-x/portal-shared-components';

interface PageNotificationProps {
notification: { open: boolean; severity: "success" | "error"; title: string } | null;
}

const PageNotification = ({ notification }: PageNotificationProps) => {
return (
notification && (
<Grid2 size={{xs: 12}}>
<PageNotifications open severity={notification.severity} showIcon title={notification.title} />
</Grid2>
)
);
};

export default PageNotification;
6 changes: 3 additions & 3 deletions ichub-frontend/src/components/general/ProductCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,9 @@ export const ProductCard = ({
<Typography
variant="h5"
sx={{
"-webkit-line-clamp": "2",
display: "-webkit-box",
"-webkit-box-orient": "vertical",
WebkitLineClamp: 2,
display: "WebkitBox",
WebkitBoxOrient: "vertical",
overflow: "hidden",
fontWeight: "bold",
fontSize: "18px",
Expand Down
48 changes: 40 additions & 8 deletions ichub-frontend/src/components/general/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,50 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

import { Menu } from '@catena-x/portal-shared-components';
import { useState, JSX } from "react";
import sidebarElements from '../../tests/payloads/sidebar-elements.json'

import { Box } from "@mui/material";

import { Storefront as StorefrontIcon, Category as CategoryIcon, People as PeopleIcon, Assignment as AssignmentIcon } from '@mui/icons-material';

const iconMap: { [key: string]: JSX.Element } = {
Storefront: <StorefrontIcon />,
Category: <CategoryIcon />,
Shared: <PeopleIcon />,
Status: <AssignmentIcon />
};

const Sidebar = () => {
const [activeIndex, setActiveIndex] = useState(0);

return (
<Menu
items={sidebarElements.map(({ title, subitems }) => ({
title,
href: '#',
children: subitems.map(({ name, link }) => ({ title: name, href: link }))
}))}
/>
<Box className="sidebarContainer">
{/* Barra de Iconos */}
<Box className="iconBar">
{sidebarElements.map((item, index) => (
<button
key={index}
className={`iconButton ${index === activeIndex ? "active" : ""}`}
onClick={() => setActiveIndex(index)}
>
{iconMap[item.icon] || <StorefrontIcon />}
</button>
))}
</Box>

{/* Contenido del Sidebar */}
<Box className="sidebarContent">
<h2>{sidebarElements[activeIndex].title}</h2>
<ul>
{sidebarElements[activeIndex].subitems.map((subitem, idx) => (
<li key={idx}>
<a href={subitem.link}>{subitem.name}</a>
</li>
))}
</ul>
</Box>
</Box>
);
};

Expand Down
Loading
Loading