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
15 changes: 10 additions & 5 deletions src/app/routes/help-videos/help-videos.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,28 @@
</header>

<main class="help-videos-content">
<h1 class="page-title">{{ 'HELP_VIDEOS_TITLE' | translate }}</h1>
<p class="page-subtitle">{{ 'HELP_VIDEOS_SUBTITLE' | translate }}</p>
<h1 class="page-title" lang="hi">{{ pageTitleHi }}</h1>
<p class="page-title-en" lang="en">{{ pageTitleEn }}</p>
<p class="page-subtitle" lang="hi">{{ pageSubtitleHi }}</p>
<p class="page-subtitle-en" lang="en">{{ pageSubtitleEn }}</p>

<ul class="video-list">
@for (video of videos; track video.id) {
<li class="video-card">
<a class="video-link" [href]="video.url" target="_blank" rel="noopener noreferrer">
<div class="thumb-wrap">
<img class="thumb" [src]="thumbnail(video)" [alt]="video.title | translate" loading="lazy" />
<img class="thumb" [src]="thumbnail(video)" [alt]="video.titleEn" loading="lazy" />
<span class="play-badge">
<mat-icon>play_arrow</mat-icon>
</span>
</div>
<div class="video-meta">
<h2 class="video-title">{{ video.title | translate }}</h2>
<h2 class="video-title" lang="hi">{{ video.titleHi }}</h2>
<p class="video-title-en" lang="en">{{ video.titleEn }}</p>
<span class="watch-cta">
{{ 'WATCH_ON_YOUTUBE' | translate }}
<span lang="hi">यूट्यूब पर देखें</span>
<span class="cta-sep" aria-hidden="true">&middot;</span>
<span lang="en">Watch on YouTube</span>
<mat-icon class="cta-icon">open_in_new</mat-icon>
</span>
</div>
Expand Down
82 changes: 69 additions & 13 deletions src/app/routes/help-videos/help-videos.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -63,26 +63,52 @@
}
}

// Hindi is the primary reading on this page; English sits under it as support.
// Devanagari needs a looser line-height than Latin at the same size.
.page-title {
margin: 0 0 8px;
margin: 0 0 2px;
font-size: 28px;
font-weight: 600;
line-height: 1.3;
line-height: 1.45;
color: #17283c;

@include ws-mixins.breakpoint-xs {
font-size: 22px;
font-size: 21px;
}
}

.page-title-en {
margin: 0 0 14px;
font-size: 17px;
font-weight: 500;
line-height: 1.3;
color: #5b6677;

@include ws-mixins.breakpoint-xs {
font-size: 14px;
margin-bottom: 10px;
}
}

.page-subtitle {
margin: 0 0 28px;
margin: 0 0 2px;
font-size: 16px;
line-height: 1.5;
color: #5b6677;
line-height: 1.6;
color: #45525f;

@include ws-mixins.breakpoint-xs {
font-size: 14px;
}
}

.page-subtitle-en {
margin: 0 0 28px;
font-size: 14px;
line-height: 1.5;
color: #77828f;

@include ws-mixins.breakpoint-xs {
font-size: 13px;
margin-bottom: 20px;
}
}
Expand All @@ -101,7 +127,11 @@
}
}

// Flex chain (card → link → meta) exists so the CTA can be pushed to the bottom
// with margin-top:auto — the two Hindi titles differ a lot in length, and without
// this the CTAs sit at different heights on desktop.
.video-card {
display: flex;
background: #fff;
border: 1px solid #e3e6ea;
border-radius: 12px;
Expand All @@ -116,7 +146,9 @@
}

.video-link {
display: block;
display: flex;
flex: 1;
flex-direction: column;
text-decoration: none;
color: inherit;

Expand All @@ -128,6 +160,7 @@

.thumb-wrap {
position: relative;
flex: none; // don't let the flex column squash the 16:9 box
width: 100%;
aspect-ratio: 16 / 9;
background: #0f1720;
Expand Down Expand Up @@ -164,6 +197,9 @@
}

.video-meta {
display: flex;
flex: 1;
flex-direction: column;
padding: 16px;

@include ws-mixins.breakpoint-xs {
Expand All @@ -172,25 +208,45 @@
}

.video-title {
margin: 0 0 12px;
font-size: 17px;
margin: 0 0 4px;
font-size: 18px;
font-weight: 600;
line-height: 1.4;
line-height: 1.5;
color: #17283c;

@include ws-mixins.breakpoint-xs {
font-size: 15px;
font-size: 16px;
}
}

.video-title-en {
margin: 0 0 14px;
font-size: 14px;
font-weight: 500;
line-height: 1.4;
color: #5b6677;

@include ws-mixins.breakpoint-xs {
font-size: 13px;
margin-bottom: 12px;
}
}

.watch-cta {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 14px;
flex-wrap: wrap;
align-self: flex-start;
margin-top: auto;
gap: 5px;
font-size: 13px;
font-weight: 600;
color: #1e8f8e;

.cta-sep {
opacity: 0.55;
}

.cta-icon {
font-size: 16px;
width: 16px;
Expand Down
80 changes: 17 additions & 63 deletions src/app/routes/help-videos/help-videos.component.ts
Original file line number Diff line number Diff line change
@@ -1,96 +1,50 @@
import { Component, OnDestroy, OnInit } from '@angular/core'
import { TranslateService } from '@ngx-translate/core'
import { Subject } from 'rxjs'
import { takeUntil } from 'rxjs/operators'
import { Component } from '@angular/core'
import { S3_END_POINTS } from '../../constants/apiConstants'
import { LanguageService } from '../../services/language.service'

export interface IHelpVideo {
id: string
url: string
title: string
titleHi: string
titleEn: string
}

/**
* Page-scoped translations.
*
* These are seeded into the translate store instead of living only in
* src/assets/i18n/*.json because the dev proxy serves /assets/** from the
* production host — local i18n edits are never picked up while running
* `yarn start`. Seeding keeps this standalone page correct in both places.
* This page deliberately shows Hindi and English together rather than switching
* on the active locale — it is shared directly with Uttar Pradesh health workers,
* so both readings are always on screen. That is also why the copy lives here as
* plain strings instead of going through ngx-translate.
*/
const HELP_VIDEO_TRANSLATIONS: { [lang: string]: { [key: string]: string } } = {
en: {
HELP_VIDEOS_TITLE: 'Help Videos',
HELP_VIDEOS_SUBTITLE: 'Watch these short videos to learn how to register and use eKshamata.',
WATCH_ON_YOUTUBE: 'Watch on YouTube',
HELP_VIDEO_HOW_TO_REGISTER: 'How to Register on eKshamata',
HELP_VIDEO_HOW_TO_USE_APP: 'How to use the E-Kshamata app after registration',
},
hi: {
HELP_VIDEOS_TITLE: 'सहायता वीडियो',
HELP_VIDEOS_SUBTITLE: 'ई-क्षमता पर पंजीकरण और उपयोग करने का तरीका जानने के लिए ये छोटे वीडियो देखें।',
WATCH_ON_YOUTUBE: 'यूट्यूब पर देखें',
HELP_VIDEO_HOW_TO_REGISTER: 'ई-क्षमता पर पंजीकरण कैसे करें',
HELP_VIDEO_HOW_TO_USE_APP: 'पंजीकरण के बाद ई-क्षमता ऐप का उपयोग कैसे करें',
},
}

@Component({
standalone: false,
selector: 'ws-app-help-videos',
templateUrl: './help-videos.component.html',
styleUrls: ['./help-videos.component.scss'],
})
export class HelpVideosComponent implements OnInit, OnDestroy {
private readonly destroy$ = new Subject<void>()

export class HelpVideosComponent {
readonly aastrikaLogo = '/fusion-assets/images/aastrika-foundation-logo.svg'
readonly upLogo = S3_END_POINTS.UP_GOV_LOGO

readonly pageTitleHi = 'ई-क्षमता सहायता वीडियो'
readonly pageTitleEn = 'eKshamata Help Videos'
readonly pageSubtitleHi = 'रजिस्टर करने और ऐप का उपयोग करने का तरीका जानने के लिए ये वीडियो देखें।'
readonly pageSubtitleEn = 'Watch these short videos to learn how to register and use eKshamata.'

readonly videos: IHelpVideo[] = [
{
id: 'aPNR0V0ezow',
url: 'https://youtu.be/aPNR0V0ezow?si=fiR8pClD-Zxcigjb',
title: 'HELP_VIDEO_HOW_TO_REGISTER',
titleHi: 'ई-क्षमता पर रजिस्टर कैसे करें',
titleEn: 'How to Register on eKshamata',
},
{
id: '747ExeI6krU',
url: 'https://youtu.be/747ExeI6krU?si=1D3yLBUt59fQt1KY',
title: 'HELP_VIDEO_HOW_TO_USE_APP',
titleHi: 'रजिस्टर करने के बाद ई-क्षमता ऐप का उपयोग कैसे करें',
titleEn: 'How to use the E-Kshamata app after registration',
},
]

constructor(
private readonly langSvc: LanguageService,
private readonly translate: TranslateService,
) { }

ngOnInit(): void {
// This page can be opened directly (no app shell bootstrap), so make sure a
// language is active before the translate pipe runs.
this.langSvc.setLanguage(this.langSvc.getCurrentLanguage())
this.seedTranslations()
// A completed i18n fetch replaces the store for that language, which would
// drop the seeded keys — put them back whenever the language (re)loads.
this.translate.onLangChange
.pipe(takeUntil(this.destroy$))
.subscribe(() => this.seedTranslations())
}

ngOnDestroy(): void {
this.destroy$.next()
this.destroy$.complete()
}

thumbnail(video: IHelpVideo): string {
return `https://img.youtube.com/vi/${video.id}/hqdefault.jpg`
}

/** Merge page strings on top of whatever the i18n loader fetched. */
private seedTranslations(): void {
Object.keys(HELP_VIDEO_TRANSLATIONS).forEach(lang => {
this.translate.setTranslation(lang, HELP_VIDEO_TRANSLATIONS[lang], true)
})
}
}
Loading