Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
26e144d
Cleanup
OscarFava Oct 31, 2025
6bd2992
Merge remote-tracking branch 'origin/develop' into ofava/vidsol-240-l…
OscarFava Nov 3, 2025
8d06d93
Refactor UI components for improved layout and styling; update welcom…
OscarFava Nov 4, 2025
ef8bb8d
Update LandingPageWelcome component layout and styling; modify welcom…
OscarFava Nov 4, 2025
e4d69d2
Wrap MUI components + use wrapped components + add standard layout to…
OscarFava Nov 4, 2025
00756d1
Avoid using useTheme to use theme as param in sx + add new MUI wrappe…
OscarFava Nov 5, 2025
aca9e39
Refactor layout components to use GridLayout; update styles and add F…
OscarFava Nov 6, 2025
e2af1e3
Fix unit testing
OscarFava Nov 6, 2025
364ce1f
Fix lint
OscarFava Nov 6, 2025
8d9c498
Fix sonarCloud
OscarFava Nov 6, 2025
33de628
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Nov 6, 2025
ca5cac8
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Nov 6, 2025
affed4d
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Nov 6, 2025
66acaf1
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Nov 6, 2025
ebbb079
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Nov 6, 2025
5dc287c
Refactor root element in index.html and wrap App component in Box for…
OscarFava Nov 7, 2025
6fe87c7
Copilot suggestions
OscarFava Nov 7, 2025
128649e
Update frontend/src/components/JoinButton/JoinButton.tsx
OscarFava Nov 7, 2025
9509188
Refactor room name input
OscarFava Nov 12, 2025
82e221e
UI/UX improvements
OscarFava Nov 13, 2025
b3460b4
Change color tokens
OscarFava Nov 13, 2025
9cf4855
Refactor JoinButton to JoinWaitRoomButton; update translations and tests
OscarFava Nov 13, 2025
4da6734
Update room input helper text for clarity in multiple languages
OscarFava Nov 13, 2025
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
6 changes: 5 additions & 1 deletion frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/images/favicon.ico" />
<link
href="https://fonts.googleapis.com/css2?family=Inter:[email protected]&display=swap"
rel="stylesheet"
/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<title>Vonage Video React Reference App</title>
</head>
<body>
<div class="bg-darkGray-100 absolute" id="root"></div>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
34 changes: 26 additions & 8 deletions frontend/src/components/Banner/Banner.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { ReactElement } from 'react';
import { AppBar, Toolbar } from '@mui/material';
import Box from '@ui/Box';
import Stack from '@ui/Stack';
import BannerDateTime from '../BannerDateTime';
import BannerLinks from '../BannerLinks';
import BannerLogo from '../BannerLogo';
Expand All @@ -12,15 +15,30 @@ import BannerLanguage from '../BannerLanguage';
*/
const Banner = (): ReactElement => {
return (
<div className="flex w-full flex-row justify-between">
<BannerLogo />
<AppBar position="static">
<Toolbar sx={{ alignItems: 'stretch' }}>
<Box sx={{ flex: 1, bgcolor: 'background.paper' }}>
<BannerLogo />
</Box>

<div className="flex px-4">
<BannerDateTime />
<BannerLanguage />
<BannerLinks />
</div>
</div>
<Box sx={{ flex: 1, bgcolor: { xs: 'background.paper', md: 'primary.light' } }}>
<Stack
direction="row"
spacing={2}
alignItems="center"
justifyContent="flex-end"
sx={{
height: '100%',
bgcolor: { xs: 'background.paper', md: 'primary.light' },
}}
>
<BannerDateTime />
<BannerLanguage />
<BannerLinks />
</Stack>
</Box>
</Toolbar>
</AppBar>
);
};

Expand Down
4 changes: 4 additions & 0 deletions frontend/src/components/BannerLogo/BannerLogo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ const BannerLogo = (): ReactElement => (
<Link to="..">
<div className="box-border" data-testid="banner-logo">
<img
style={{
marginLeft: '16px',
marginTop: '12px',
}}
className="hidden h-[72px] pl-4 pr-8 md:flex"
src="/images/vonage-logo-desktop.svg"
alt="Vonage-desktop-logo"
Expand Down
41 changes: 0 additions & 41 deletions frontend/src/components/JoinButton/JoinButton.tsx

This file was deleted.

3 changes: 0 additions & 3 deletions frontend/src/components/JoinButton/index.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { ReactElement } from 'react';
import { useTranslation } from 'react-i18next';
import Stack from '@ui/Stack';
import Typography from '@ui/Typography';
import Separator from '../Separator';

/**
Expand All @@ -11,11 +13,19 @@ import Separator from '../Separator';
const JoinContainerSeparator = (): ReactElement => {
const { t } = useTranslation();
return (
<div className="flex w-full items-center">
<Stack direction="row" alignItems="center" width="100%" sx={{ my: 4 }}>
<Separator orientation="left" />
{t('common.or')}
<Typography
variant="body2"
sx={(theme) => ({
color: theme.palette.tertiary?.main ?? theme.palette.text.secondary,
mx: 2,
})}
>
{t('common.or')}
</Typography>
<Separator orientation="right" />
</div>
</Stack>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ describe('JoinExistingRoom', () => {
render(<JoinExistingRoom />);

expect(screen.getByTestId('JoinExistingRoom')).toBeInTheDocument();
expect(screen.getByTestId('KeyboardIcon')).toBeInTheDocument();
expect(screen.getByText('Join')).toBeInTheDocument();
expect(screen.getByPlaceholderText(/Enter room name/i)).toBeInTheDocument();
expect(screen.getByText('Join waiting room')).toBeInTheDocument();
expect(screen.getAllByText(/Room name/i)[0]).toBeInTheDocument();
});
});
15 changes: 11 additions & 4 deletions frontend/src/components/JoinExistingRoom/JoinExistingRoom.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ReactElement, useState } from 'react';
import JoinButton from '../JoinButton';
import Stack from '@ui/Stack';
import JoinWaitRoomButton from '../JoinWaitRoomButton';
import RoomNameInput from '../RoomNameInput';

/**
Expand All @@ -13,16 +14,22 @@ const JoinExistingRoom = (): ReactElement => {
const [hasError, setHasError] = useState(false);

return (
<form className="mt-[35px] w-72 flex-row" data-testid="JoinExistingRoom">
<Stack
direction="column"
component="form"
data-testid="JoinExistingRoom"
spacing={3}
sx={{ mb: 6, width: '100%' }}
>
<RoomNameInput
setRoomName={setRoomName}
roomName={roomName}
hasError={hasError}
setHasError={setHasError}
/>

<JoinButton roomName={roomName} isDisabled={hasError} />
</form>
<JoinWaitRoomButton roomName={roomName} isDisabled={false} setHasError={setHasError} />
</Stack>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { render, screen, fireEvent } from '@testing-library/react';
import { MemoryRouter, useNavigate } from 'react-router-dom';
import { describe, expect, it, Mock, vi } from 'vitest';
import JoinButton from './JoinButton';
import { describe, expect, it, Mock, vi, beforeEach } from 'vitest';
import JoinWaitRoomButton from './JoinWaitRoomButton';

vi.mock('react-router-dom', async () => {
const mod = await vi.importActual<typeof import('react-router-dom')>('react-router-dom');
Expand All @@ -12,13 +12,20 @@ vi.mock('react-router-dom', async () => {
});

const mockNavigate = vi.fn();
const mockSetHasError = vi.fn();

describe('JoinWaitRoomButtonComponent', () => {
beforeEach(() => {
vi.clearAllMocks();
mockNavigate.mockClear();
mockSetHasError.mockClear();
});

describe('JoinButtonComponent', () => {
it('should navigate to the waiting room if the room name is valid', () => {
(useNavigate as Mock).mockReturnValue(mockNavigate);
render(
<MemoryRouter>
<JoinButton roomName="test-room" isDisabled={false} />
<JoinWaitRoomButton roomName="test-room" isDisabled={false} setHasError={mockSetHasError} />
</MemoryRouter>
);

Expand All @@ -27,27 +34,17 @@ describe('JoinButtonComponent', () => {
expect(mockNavigate).toHaveBeenCalledWith('/waiting-room/test-room');
});

it('should not navigate to the waiting room if the room name is empty', () => {
it('should not navigate and set error if the room name is empty', () => {
(useNavigate as Mock).mockReturnValue(mockNavigate);
render(
<MemoryRouter>
<JoinButton roomName="" isDisabled={false} />
<JoinWaitRoomButton roomName="" isDisabled={false} setHasError={mockSetHasError} />
</MemoryRouter>
);

const button = screen.getByRole('button');
expect(button).toBeDisabled();
});

it('should not navigate to the waiting room if the button is disabled', () => {
(useNavigate as Mock).mockReturnValue(mockNavigate);
render(
<MemoryRouter>
<JoinButton roomName="test-room" isDisabled />
</MemoryRouter>
);
fireEvent.click(screen.getByRole('button'));

const button = screen.getByRole('button');
expect(button).toBeDisabled();
expect(mockNavigate).not.toHaveBeenCalled();
expect(mockSetHasError).toHaveBeenCalledWith(true);
});
});
52 changes: 52 additions & 0 deletions frontend/src/components/JoinWaitRoomButton/JoinWaitRoomButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import Button from '@ui/Button';
import { Dispatch, MouseEvent, ReactElement, SetStateAction } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';

export type JoinWaitRoomButtonProps = {
roomName: string;
isDisabled: boolean;
setHasError: Dispatch<SetStateAction<boolean>>;
};

/**
* JoinWaitRoomButton Component
*
* This component returns a button that takes a user to the meeting.
* @param {JoinWaitRoomButtonProps} props - the props for this component.
* @property {string} roomName - the name of the room to join.
* @property {boolean} isDisabled - whether the button is disabled.
* @property {Dispatch<SetStateAction<boolean>>} setHasError - function to set the error state.
* @returns {ReactElement} - the join room button.
*/
const JoinWaitRoomButton = ({
roomName,
isDisabled,
setHasError,
}: JoinWaitRoomButtonProps): ReactElement => {
const { t } = useTranslation();
const navigate = useNavigate();

const handleJoin = (event: MouseEvent) => {
event.preventDefault();
if (roomName === '') {
setHasError(true);
return;
}
navigate(`/waiting-room/${roomName}`);
};

return (
<Button
variant="outlined"
disabled={isDisabled}
sx={{ ml: 1 }}
onClick={handleJoin}
type="submit"
>
{t('button.joinWaitingRoom')}
</Button>
);
};

export default JoinWaitRoomButton;
3 changes: 3 additions & 0 deletions frontend/src/components/JoinWaitRoomButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import JoinWaitRoomButton from './JoinWaitRoomButton';

export default JoinWaitRoomButton;
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ describe('LandingPageWelcome', () => {
it('renders the welcome heading and applies correct styling', () => {
render(<LandingPageWelcome />);

const textHeading = screen.getByText('Welcome to the Vonage Video React App');
const textHeading = screen.getByText(
'Power your business with video that transforms customer satisfaction.'
);
expect(textHeading).toBeInTheDocument();
});
});
Loading