Skip to content

ClubHub – Fáza 1: Inštrukcie ​

Tento dokument hovorí, ako budete vo Fáze 1 pracovať a kto čo robí ktorý týždeň. Čo má appka vedieť, nájdete v špecifikácii Fázy 1.

Ako pracujeme ​

V tíme ste 2 vývojári, A a B (v trojici aj C). Všetci programujete a každý týždeň má každý z vás vlastnú úlohu. Každú zmenu skontroluje ten druhý, než sa zlúči.

Ako vzniká jedna úloha ​

  1. Úlohy z plánu po týždňoch si zapíšete na board v Notione a dohodnete sa, kto z vás je A a kto B.
  2. Vývojár si úlohu priradí a vytvorí si z hlavnej vetvy projektu novú vetvu s názvom feature/<nazov-ulohy>, napr. feature/karta-podujatia.
  3. Pred začatím napíše krátky plán úlohy podľa stránky Ako plánovať úlohu a dá ho prečítať kolegovi.
  4. Hotovú úlohu pošle ako merge request.
  5. Druhý člen tímu spraví code review podľa stránky Code review; po schválení sa zmena zlúči.
  6. Na konci fázy odprezentujete mentorovi, čo ste spravili.

Definition of Done ​

Úloha je hotová, keď:

  • spĺňa všetky akceptačné kritériá svojej user story,
  • dodržiava technické zásady,
  • prešla code review a je zlúčená do hlavnej vetvy,
  • v konzole nie sú chyby.

Plán po týždňoch ​

Fáza 1 má 6 piatkov (9. 10. – 20. 11. 2026, 30. 10. sú jesenné prázdniny). Čo nestihnete na hodine, dokončite na pracovných hodinách alebo doma do ďalšieho piatku.

Ak ste v tíme traja, vývojár C preberá pri každom týždni časť práce A alebo B – je to uvedené pri danom týždni. Odkazy A1, B1… vedú na obrazovky v dizajne.

1. týždeň · 9. 10. – Kickoff a setup ​

Cieľ: viete, čo budete robiť, a obaja máte projekt rozbehnutý lokálne. Dostanete odkaz na dizajn (je v špecifikácii) a mock dáta; dátumy v dátach si upravte podľa potreby.

  • Vývojár A: podľa stránky Setup projektu založí repozitár v GitLabe, pridá B, vytvorí a uprace projekt, pushne ho a nastaví ochranu hlavnej vetvy.
  • Vývojár B: nainštaluje si prostredie podľa Setup projektu, krok 1. Založí board v Notione a zapíše do neho úlohy z plánu po týždňoch, aby ste videli, ako napredujete. Na konci si naklonuje projekt a spustí ho lokálne.
  • Vývojár C (ak ste traja): nainštaluje si prostredie, pomáha B s boardom, na konci si naklonuje projekt.

2. týždeň · 16. 10. – Layout a karta ​

Cieľ: navigácia appky a karta podujatia.

  • Vývojár A: US-01 – layout so spodnou lištou a 2 prázdnymi obrazovkami (Podujatia, Uložené). Dizajn: spodná lišta v A1 a C1.
  • Vývojár B: US-02 – komponent karty podujatia podľa dizajnu vrátane náhradného obrázka podľa kategórie. Vloží mock dáta do projektu: events.json – vložte ich napr. do src/plugins/app@events/_data/events.json a dátumy si upravte podľa potreby. Dizajn: karta v A1, v design systéme komponenty Event Card a Category Image.
  • Vývojár C (ak ste traja): vloží mock dáta a urobí náhradný obrázok kategórie – gradient s ikonou podľa dizajnu. B robí len kartu.

3. týždeň · 23. 10. – Zoznam a detail ​

Cieľ: zoznam podujatí a detail.

  • Vývojár A: US-02 – obrazovka Podujatia: načítanie dát, zoradenie, skrytie minulých podujatí, prázdny stav, karty od B. Dizajn: A1, prázdny stav A1b.
  • Vývojár B: US-03 – obrazovka detailu so všetkými údajmi, logikou ceny, hláškou „Podujatie sa nenašlo“ a prechodom z karty. Dizajn: B1, B1b.
  • Vývojár C (ak ste traja): prázdny stav zoznamu (A1b) a hláška „Podujatie sa nenašlo“ (B1b). A a B robia len hlavné obrazovky.

4. týždeň · 6. 11. – Uloženie a hľadanie ​

Cieľ: uloženie podujatí a vyhľadávanie.

  • Vývojár A: US-06 – ukladanie „Zaujíma ma“, ktoré prežije reštart appky, tlačidlo na karte aj v detaile, obrazovka Uložené s prázdnym stavom. Dizajn: srdiečko v A1 a B1, obrazovka C1, prázdny stav C1b.
  • Vývojár B: US-04 – vyhľadávanie bez ohľadu na diakritiku a veľkosť písmen, hláška pri prázdnom výsledku. Dizajn: A1, prázdny výsledok A1c.
  • Vývojár C (ak ste traja): obrazovka Uložené s prázdnym stavom (C1, C1b). A robí len ukladanie a tlačidlá.

5. týždeň · 13. 11. – Filtre ​

Cieľ: filtre spolu s vyhľadávaním.

  • Vývojár A: US-05 – filter kategórií (viac naraz) a filter obdobia. Dizajn: A1.
  • Vývojár B: US-05 – zobrazenie aktívnych filtrov, zrušenie všetkých, prepojenie filtrov s vyhľadávaním. Zachovanie filtrov po návrate z detailu. Dizajn: aktívne filtre a „Zrušiť filtre“ v A1c.
  • Vývojár C (ak ste traja): filter obdobia. A robí len filter kategórií.

6. týždeň · 20. 11. – Prezentácia ​

Cieľ: hotová fáza odprezentovaná mentorovi.

  • Vývojár A: otestuje US-01 až US-03 podľa akceptačných kritérií v prehliadači v mobilnom zobrazení a opraví chyby.
  • Vývojár B: otestuje US-04 až US-06 rovnako a opraví chyby. Spolu s A pripraví 10-minútovú prezentáciu.
  • Vývojár C (ak ste traja): testovanie v prehliadači v mobilnom zobrazení, príprava prezentácie.

Technické pokyny ​

Ukážky nižšie sú len kostra – vzhľad a texty robte podľa dizajnu a akceptačných kritérií. Cesty k súborom zodpovedajú štruktúre z technických zásad.

Spodná lišta je layout, v ktorom sú ostatné obrazovky ako deti v routeri. V router nastavte:

js
routes: [
	{ path: '/', redirect: '/tabs/events' },
	{
		path: '/tabs/',
		component: () => import('../_layout/tabs-layout.vue'),
		children: [
			{ path: '', redirect: '/tabs/events' },
			{ path: 'events', component: () => import('../../app@events/events-list.vue') },
			{ path: 'events/:id', component: () => import('../../app@events/event-detail/event-detail.vue') },
			{ path: 'saved', component: () => import('../../app@saved/saved.vue') },
		],
	},
],

Layout app/_layout/tabs-layout.vue obsahuje ion-tabs so spodnou lištou. Každé tlačidlo má href na svoju obrazovku:

vue
<template>
	<ion-page>
		<ion-tabs>
			<ion-router-outlet />
			<ion-tab-bar slot="bottom">
				<ion-tab-button tab="events" href="/tabs/events">
					<ion-icon :icon="calendarOutline" />
					<ion-label>Podujatia</ion-label>
				</ion-tab-button>
				<ion-tab-button tab="saved" href="/tabs/saved">
					<ion-icon :icon="heartOutline" />
					<ion-label>Uložené</ion-label>
				</ion-tab-button>
			</ion-tab-bar>
		</ion-tabs>
	</ion-page>
</template>

<script setup>
import { IonPage, IonTabs, IonRouterOutlet, IonTabBar, IonTabButton, IonIcon, IonLabel } from '@ionic/vue'
import { calendarOutline, heartOutline } from 'ionicons/icons'
</script>

Každá obrazovka (events-list.vue, saved.vue…) má v šablóne ako koreň ion-page a v ňom ion-content.

Načítanie mock dát (US-02) ​

Súbor events.json vložte do app@events/_data/ a naimportujte ho ako obyčajný modul. Dostanete priamo pole podujatí:

js
import events from './_data/events.json'

Detail podľa ID v adrese (US-03) ​

Na detail sa dostanete cez /tabs/events/<id>. Z karty naň prejdete napríklad router.push(`/tabs/events/${event.id}`). V detaile si ID prečítate z adresy cez useRoute – je to text, preto ho zmeňte na číslo:

js
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import events from '../_data/events.json'

const route = useRoute()
const event = computed(() => events.find(item => item.id === Number(route.params.id)))

Keď event nie je nájdený (undefined), zobrazte hlášku „Podujatie sa nenašlo“.

Náhradný obrázok kategórie (US-02) ​

Keď podujatie nemá obrázok, karta aj detail ukážu fialový gradient s ikonou kategórie (v dizajne komponent Category Image). Je to div s gradientom z palety a ion-icon v strede, nie obrázok:

KategóriaIkona
ŠportfootballOutline
KultúramusicalNotesOutline
Veda a technikaflaskOutline
VýletymapOutline
KrúžkycolorPaletteOutline
OstatnéellipsisHorizontalOutline
vue
<template>
	<div class="flex aspect-video items-center justify-center" :style="{ background: 'var(--gradient-primary)' }">
		<ion-icon :icon="categoryIcon" class="size-16 text-primary-contrast" />
	</div>
</template>

Priradenie kategórie k ikone majte na jednom mieste, napr. v _utils/category-icons.js, aby ho karta aj detail používali rovnako.

Formát dátumu (US-02, US-03) ​

Dátumy sú v dátach ako text, napr. "2026-12-18T17:00:00". Do tvaru „18. 12. 2026 17:00“ ich prevedie funkcia v app/_utils/format-date.js:

js
export function formatDate(isoString) {
	return new Date(isoString).toLocaleString('sk-SK', {
		day: 'numeric',
		month: 'numeric',
		year: 'numeric',
		hour: '2-digit',
		minute: '2-digit',
	})
}

Vyhľadávanie bez diakritiky (US-04) ​

Text vyhľadávania aj názov podujatia najprv upravte rovnakou funkciou – bez diakritiky, malými písmenami a bez medzier na okrajoch – a až potom ich porovnajte. Funkcia v app/_utils/normalize-text.js:

js
export function normalizeText(text) {
	return text
		.normalize('NFD')
		.replace(/[\u0300-\u036f]/g, '')
		.toLowerCase()
		.trim()
}

Použitie: normalizeText(event.title).includes(normalizeText(query)).

Uloženie „Zaujíma ma“ (US-06) ​

Do localStorage sa dá uložiť len text, preto pole ID uložených podujatí prevediete cez JSON.stringify a pri načítaní späť cez JSON.parse. Funkcie v app/_utils/saved-events.js:

js
const STORAGE_KEY = 'savedEventIds'

export function loadSavedIds() {
	return JSON.parse(localStorage.getItem(STORAGE_KEY) ?? '[]')
}

export function storeSavedIds(ids) {
	localStorage.setItem(STORAGE_KEY, JSON.stringify(ids))
}

Pri každom kliknutí na „Zaujíma ma“ ID pridajte do poľa alebo ho z neho odoberte a pole znova uložte cez storeSavedIds. Keď appku zatvoríte a otvoríte, loadSavedIds vráti uložené ID.

Na čo si dať pozor ​

  • Týždeň 1: kým A zakladá projekt, B nemá čo kódovať. Preto robí board a prostredie a projekt si naklonuje až na konci hodiny.
  • Týždeň 3: A potrebuje kartu od B z 2. týždňa. Ak ešte nie je zlúčená, A začne s dočasnou kartou a neskôr ju vymení.
  • Týždeň 5: obaja meníte tú istú obrazovku, takže pri zlúčení vzniknú konflikty. Dohodnite sa na začiatku, kto zlúči ako prvý; druhý si potom stiahne zmeny a konflikty vyrieši.

Odovzdanie fázy ​

Fáza končí 20. 11. prezentáciou, na ktorej každý tím za 10 minút ukáže mentorovi, čo spravil.

Po prezentácii dostanete zadanie Fázy 2.