Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
5b013cc
Updated NewsCard.tsx
Varkopat Jul 31, 2026
3c9bf97
Update NewsCard component layout and styles based on new Figma designs
Varkopat Jul 31, 2026
c1068be
chore: update altLogoold.png image asset
Varkopat Aug 3, 2026
aff656c
Merge branch 'dev' into Varkopat/enhancement/664-update-newscard-comp…
Varkopat Aug 4, 2026
4faacb7
refactor: update NewsCard component layout and styles based on new Fi…
Varkopat Aug 5, 2026
d74772b
refactor: update NewsCard component styles and layout based on new de…
Varkopat Aug 6, 2026
f442b45
refactor: update NewsCard and NewsPage components layout and styles b…
Varkopat Aug 6, 2026
89d5fd1
refactor: update layout and styles of NewsCard and NewsPage component…
Varkopat Aug 10, 2026
7b779aa
refactor: removed hardcoded default publisher value in NewsCard compo…
Varkopat Aug 12, 2026
0ac81ab
refactor: update NewsCard component layout and styles based on new de…
Varkopat Aug 12, 2026
23751c9
refactor: small improvements to UI
Varkopat Aug 17, 2026
b647682
The mobile cards now display full-width within their container with p…
Varkopat Aug 17, 2026
6cd2fc0
1. Mobile title spacing: Reduced margin-bottom from 20px to 8px so th…
Varkopat Aug 17, 2026
9cd5128
refactor: update NewsCard and NewsPage styles for improved layout and…
Varkopat Aug 18, 2026
6b2d985
fix: correct width calculation for news content on medium screens
Varkopat Aug 18, 2026
cd37e1c
refactor: update NewsCard layout to align with new Figma designs. On …
Varkopat Aug 18, 2026
9c5529e
refactor: update NewsCard width to be responsive based on new design …
Varkopat Aug 20, 2026
cec2231
test: add unit tests for NewsCard component to verify rendering and f…
Varkopat Aug 24, 2026
f81d3c3
refactor: update font styling for mobile NewsCard title
Varkopat Aug 24, 2026
3c8fc6e
refactor: update NewsCard component layout to match new Figma designs…
Varkopat Aug 31, 2026
83568c5
refactor: update NewsCard layout and styling for noImage state
Varkopat Sep 1, 2026
d153e65
refactor: integrate PageTitle component into NewsPage layout for impr…
Varkopat Sep 1, 2026
c85779a
refactor: rename PageTitle class to title for consistency with design…
Varkopat Sep 1, 2026
f770e14
test: mock usePathname in NewsPage tests for consistent routing
Varkopat Sep 1, 2026
213c47d
refactor: update NewsCard layout gaps for improved spacing consistency
Varkopat Sep 3, 2026
f3c2924
refactor: update NewsCard layout dimensions based on new design speci…
Varkopat Sep 11, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,10 @@
.newsGrid {
display: grid;
gap: 30px;
max-width: 1000px;
max-width: 716px;
margin: 0 auto;
grid-template-columns: repeat(auto-fill, minmax(450px, 1fr));
grid-template-columns: minmax(0, 1fr);
justify-content: center;
@media (max-width: 480px) {
grid-template-columns: 1fr;
}
}

.newsHeader {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,13 @@
.newsGrid {
display: grid;
gap: 20px;
grid-template-columns: repeat(auto-fill, minmax(450px, 1fr));
grid-template-columns: minmax(0, 716px);
justify-content: center;
@media (max-width: 480px) {
grid-template-columns: 1fr;
}
margin-bottom: 1.5em;

@media (max-width: breakpoint(sm)) {
grid-template-columns: minmax(0, 1fr);
}
}

.readmoreText {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,52 @@ $touchSize: 1023px;
.NewsPage {
min-height: 80vh;
}

.newsContent {
width: min(1440px, 100%);
height: min(255px, 100%);
margin: 0 auto;

@media (max-width: breakpoint(md)) {
width: min(768px, calc(100% - 28px));
}

@media (max-width: breakpoint(sm)) {
width: min(328px, calc(100% - 28px));
height: min(516px, 100%);
}
}

.title {
font: var(--font-sw-xxl);
text-align: center;
padding: 0;
color: var(--primary-color);
margin: 0 0 12px;

h1 {
font: var(--font-sw-5xl);
text-align: left;
letter-spacing: -4%;
width: 1440px;
height: 129px;
gap: var(--spacing-800);
padding: 0;
color: var(--primary-color);
margin: 0;
}

@media (max-width: $touchSize) {
order: 0;
border-right: unset;
h1 {
text-align: left;
}
}

@media (max-width: breakpoint(md)) {
order: 1;
margin-right: 30px;
@media (max-width: breakpoint(sm)) {
h1 {
gap: 10px;
width: auto;
height: auto;
margin-bottom: 8px;
font: var(--font-sw-xl);
text-align: center;
}
}
}

Expand All @@ -35,10 +67,11 @@ $touchSize: 1023px;
.newsGrid {
display: grid;
gap: 20px;
grid-template-columns: repeat(auto-fill, minmax(450px, 1fr));
justify-content: center;
@media (max-width: 480px) {
grid-template-columns: 1fr;
grid-template-columns: minmax(0, 1fr);
justify-content: stretch;

@media (max-width: breakpoint(sm)) {
grid-template-columns: minmax(0, 1fr);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { act, render, screen, waitFor } from '@testing-library/react';
import NewsPage from './NewsPage';
import { useGetNewsQuery } from '@/entities/NewsV2';
import { useGetTotalNewsCountQuery } from '@/entities/NewsV2/Api/newsApi';

const mockIntersectionObservers: MockIntersectionObserver[] = [];

jest.mock('next/navigation', () => ({
useParams: jest.fn(() => ({ lng: 'en' })),
usePathname: jest.fn(() => '/en/news'),
}));

jest.mock('@/shared/i18n', () => ({
useClientTranslation: jest.fn(() => ({
t: (key: string) => key,
})),
}));

jest.mock('@/entities/NewsV2', () => ({
useGetNewsQuery: jest.fn(),
formatNews: (news: Array<any>, lngCode: string) =>
news.map((item) => ({
id: item.id,
date: item.date,
title:
item.translations.find((translation: any) => translation.languages_code === lngCode)
?.title ?? '',
previewText:
item.translations.find((translation: any) => translation.languages_code === lngCode)
?.preview_text ?? '',
titlePicture: item.titlePicture,
})),
}));

jest.mock('@/entities/NewsV2/Api/newsApi', () => ({
useGetTotalNewsCountQuery: jest.fn(),
}));

jest.mock('@/widgets/NewsCard', () => ({
NewsCard: ({ id, title, previewText }: { id: number; title: string; previewText?: string }) => (
<a href={`/news/${id}`}>
{title}
{previewText}
</a>
),
}));

jest.mock('@/shared/ui/SkeletonLoader/ui/SkeletonLoader', () => ({
SkeletonLoaderForNewsPage: ({ numberOfCards }: { numberOfCards: number }) => (
<div data-testid="news-skeleton">{numberOfCards}</div>
),
}));

class MockIntersectionObserver {
private readonly callback: (entries: IntersectionObserverEntry[]) => void;

constructor(callback: (entries: IntersectionObserverEntry[]) => void) {
this.callback = callback;
mockIntersectionObservers.push(this);
}

observe = jest.fn();
disconnect = jest.fn();

triggerIntersection() {
this.callback([{ isIntersecting: true } as IntersectionObserverEntry]);
}
}

describe('NewsPage', () => {
const mockUseGetNewsQuery = useGetNewsQuery as jest.Mock;
const mockUseGetTotalNewsCountQuery = useGetTotalNewsCountQuery as jest.Mock;

const createNews = (id: number) => ({
id,
date: `2026-08-${String(id).padStart(2, '0')}`,
titlePicture: id === 1 ? { id: 'image-1' } : null,
translations: [
{
languages_code: 'en-US',
title: `News ${id}`,
preview_text: `Preview ${id}`,
},
],
});
const firstPageNews = [createNews(1)];
const secondPageNews = [createNews(2)];
const finalPageNews = [1, 2, 3, 4, 5].map(createNews);

beforeEach(() => {
jest.clearAllMocks();
mockIntersectionObservers.length = 0;
Object.defineProperty(global, 'IntersectionObserver', {
configurable: true,
writable: true,
value: MockIntersectionObserver,
});
jest.requireMock('next/navigation').usePathname.mockReturnValue('/en/news');
mockUseGetNewsQuery.mockImplementation(({ page }: { page: number }) => ({
data: page === 1 ? firstPageNews : secondPageNews,
}));
mockUseGetTotalNewsCountQuery.mockReturnValue({ data: 1 });
});

it('renders the translated page title and fetched news cards', async () => {
render(<NewsPage />);

expect(screen.getByRole('heading', { level: 1, name: 'head-title' })).toBeInTheDocument();
const newsLink = await screen.findByRole('link', { name: /News 1/ });
expect(newsLink).toHaveTextContent('News 1');
expect(newsLink).toHaveTextContent('Preview 1');
expect(newsLink).toHaveAttribute('href', '/news/1');
expect(mockUseGetNewsQuery).toHaveBeenCalledWith({
limit: 6,
page: 1,
categorySlug: undefined,
});
});

it('shows six skeleton cards while news is loading', () => {
mockUseGetNewsQuery.mockReturnValue({ data: undefined });

render(<NewsPage />);

expect(screen.getByTestId('news-skeleton')).toHaveTextContent('6');
});

it('shows the no-more-news message after the final page', async () => {
mockUseGetNewsQuery.mockReturnValue({ data: finalPageNews });
mockUseGetTotalNewsCountQuery.mockReturnValue({ data: 1 });

render(<NewsPage />);

expect(await screen.findByText('no-more-news')).toBeInTheDocument();
});

it('loads the next page when the sentinel intersects', async () => {
mockUseGetTotalNewsCountQuery.mockReturnValue({ data: 7 });

render(<NewsPage />);
await waitFor(() => expect(mockIntersectionObservers.length).toBeGreaterThan(0));

act(() => {
mockIntersectionObservers[0].triggerIntersection();
});

expect(await screen.findByRole('link', { name: /News 2/ })).toBeInTheDocument();
expect(mockUseGetNewsQuery).toHaveBeenLastCalledWith({
limit: 6,
page: 2,
categorySlug: undefined,
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -95,26 +95,28 @@ const NewsPage = () => {
alternate={true}
searchVisible={false}
/>
<div className={cls.newsGrid}>
{groupedNews.map((news) => {
const imageSrc = news.titlePicture?.id
? `${directusBaseUrl}/assets/${news.titlePicture.id}`
: undefined;
return (
<NewsCard
key={news.id}
titlePicture={imageSrc}
title={news.title}
previewText={news.previewText}
date={news.date}
id={news.id}
/>
);
})}
<div className={cls.newsContent}>
<div className={cls.newsGrid}>
{groupedNews.map((news) => {
const imageSrc = news.titlePicture?.id
? `${directusBaseUrl}/assets/${news.titlePicture.id}`
: undefined;
return (
<NewsCard
key={news.id}
titlePicture={imageSrc}
title={news.title}
previewText={news.previewText}
date={news.date}
id={news.id}
/>
);
})}

{isLoading && <SkeletonLoaderForNewsPage numberOfCards={limit} />}
{isLoading && <SkeletonLoaderForNewsPage numberOfCards={limit} />}

{hasMoreNewsState && !isLoading && <div ref={observeElementRef} />}
{hasMoreNewsState && !isLoading && <div ref={observeElementRef} />}
</div>
</div>
{renderNoMoreNews()}
</Container>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading