Add Student Welcome Guide, legal pages, and working newsletter
Student Welcome Guide (Phase 1): - Landing + 5 topic pages (journey, bachelor, master, deadlines, eVS) in EN/SI/MK, reusing the article auto-TOC - New css/pages/_guide.css components and a 3:1 hero image placeholder - Functional client-side "Build my route" tool (student-guide.js) - "Student Welcome Guide" menu link wired site-wide Legal pages: - Trilingual Privacy Policy and Cookie Policy (GDPR-oriented, MailerLite disclosed, IP RS complaint route) - Footer legal strip + Organisation column links wired site-wide, depth-aware, plus header/footer templates Newsletter: - MailerLite subscribe handler in main.js upgrades both form variants on every page: validation, double opt-in, inline trilingual status - Subscribe status styles in css/pages/_projects.css Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
bf70a10a14
commit
cee9f1da10
113 files changed
+9043
-346
No files matched your search
@@ -0,0 +1,190 @@
|
||||
/* ==========================================================================
|
||||
Student Welcome Guide — "Build my route"
|
||||
Client-side personalised checklist for the guide landing page.
|
||||
The landing page sets <div class="guide-route" data-lang="en|si|mk">.
|
||||
Links point to sibling guide pages (../<slug>/) and only reference pages
|
||||
that exist, so there are no dead links.
|
||||
========================================================================== */
|
||||
(function () {
|
||||
var root = document.querySelector('.guide-route');
|
||||
if (!root) return;
|
||||
var lang = root.getAttribute('data-lang') || 'en';
|
||||
|
||||
// Slugs of pages that exist and are safe to link to.
|
||||
var S = {
|
||||
journey: 'complete-student-journey',
|
||||
bachelor: 'bachelor-application',
|
||||
master: 'master-application',
|
||||
deadlines: 'application-deadlines',
|
||||
evs: 'evs-application-guide'
|
||||
};
|
||||
|
||||
var T = {
|
||||
en: {
|
||||
heading: 'Build my route',
|
||||
sub: 'Answer a few questions and we will outline your next steps.',
|
||||
build: 'Show my route',
|
||||
reset: 'Reset',
|
||||
need: 'Please choose at least your level and your current stage.',
|
||||
resultHead: 'Your route',
|
||||
contextParts: { level: 'Level', phase: 'Stage', uni: 'Institution', city: 'City', year: 'Academic year' },
|
||||
fields: {
|
||||
level: 'Level of study', phase: 'Where are you now?', uni: 'University', city: 'Study city', year: 'Academic year'
|
||||
},
|
||||
pick: 'Select',
|
||||
levels: { bachelor: 'Bachelor', master: 'Master' },
|
||||
phases: { exploring: 'I am exploring', applying: 'I am applying', accepted: 'I have been accepted', moving: 'I am preparing to move', arrived: 'I am already in Slovenia' },
|
||||
unis: { ul: 'University of Ljubljana', um: 'University of Maribor', up: 'University of Primorska', ung: 'University of Nova Gorica', other: 'Another institution' },
|
||||
cities: { ljubljana: 'Ljubljana', maribor: 'Maribor', koper: 'Koper', 'nova-gorica': 'Nova Gorica', celje: 'Celje', other: 'Another city' },
|
||||
yourUni: 'your chosen university', yourCity: 'your study city',
|
||||
link: { journey: 'the full journey', bachelor: 'the bachelor application', master: 'the master application', deadlines: 'current deadlines', evs: 'the eVŠ guide' }
|
||||
},
|
||||
si: {
|
||||
heading: 'Ustvari mojo pot',
|
||||
sub: 'Odgovorite na nekaj vprašanj in orisali bomo vaše naslednje korake.',
|
||||
build: 'Prikaži mojo pot',
|
||||
reset: 'Ponastavi',
|
||||
need: 'Izberite vsaj stopnjo študija in vašo trenutno fazo.',
|
||||
resultHead: 'Vaša pot',
|
||||
contextParts: { level: 'Stopnja', phase: 'Faza', uni: 'Institucija', city: 'Mesto', year: 'Študijsko leto' },
|
||||
fields: {
|
||||
level: 'Stopnja študija', phase: 'Kje ste zdaj?', uni: 'Univerza', city: 'Študijsko mesto', year: 'Študijsko leto'
|
||||
},
|
||||
pick: 'Izberite',
|
||||
levels: { bachelor: 'Dodiplomski', master: 'Magistrski' },
|
||||
phases: { exploring: 'Šele raziskujem', applying: 'Prijavljam se', accepted: 'Sprejet sem', moving: 'Pripravljam se na selitev', arrived: 'Sem že v Sloveniji' },
|
||||
unis: { ul: 'Univerza v Ljubljani', um: 'Univerza v Mariboru', up: 'Univerza na Primorskem', ung: 'Univerza v Novi Gorici', other: 'Druga ustanova' },
|
||||
cities: { ljubljana: 'Ljubljana', maribor: 'Maribor', koper: 'Koper', 'nova-gorica': 'Nova Gorica', celje: 'Celje', other: 'Drugo mesto' },
|
||||
yourUni: 'izbrano univerzo', yourCity: 'vaše študijsko mesto',
|
||||
link: { journey: 'celotno pot', bachelor: 'prijavo na dodiplomski študij', master: 'prijavo na magistrski študij', deadlines: 'trenutne roke', evs: 'navodila za eVŠ' }
|
||||
},
|
||||
mk: {
|
||||
heading: 'Создади го мојот пат',
|
||||
sub: 'Одговорете на неколку прашања и ќе ги оцртаме вашите следни чекори.',
|
||||
build: 'Прикажи го мојот пат',
|
||||
reset: 'Ресетирај',
|
||||
need: 'Изберете барем степен на студии и вашата тековна фаза.',
|
||||
resultHead: 'Вашиот пат',
|
||||
contextParts: { level: 'Степен', phase: 'Фаза', uni: 'Институција', city: 'Град', year: 'Академска година' },
|
||||
fields: {
|
||||
level: 'Степен на студии', phase: 'Каде сте сега?', uni: 'Универзитет', city: 'Град на студирање', year: 'Академска година'
|
||||
},
|
||||
pick: 'Изберете',
|
||||
levels: { bachelor: 'Додипломски', master: 'Магистерски' },
|
||||
phases: { exploring: 'Сè уште истражувам', applying: 'Се пријавувам', accepted: 'Примен сум', moving: 'Се подготвувам за преселба', arrived: 'Веќе сум во Словенија' },
|
||||
unis: { ul: 'Универзитет во Љубљана', um: 'Универзитет во Марибор', up: 'Универзитет на Приморска', ung: 'Универзитет во Нова Горица', other: 'Друга институција' },
|
||||
cities: { ljubljana: 'Љубљана', maribor: 'Марибор', koper: 'Копер', 'nova-gorica': 'Нова Горица', celje: 'Целје', other: 'Друг град' },
|
||||
yourUni: 'избраниот универзитет', yourCity: 'вашиот град на студирање',
|
||||
link: { journey: 'целосниот пат', bachelor: 'пријавата за додипломски', master: 'пријавата за магистерски', deadlines: 'тековните рокови', evs: 'водичот за eVŠ' }
|
||||
}
|
||||
};
|
||||
|
||||
// Step templates per phase. {uni}/{city} are interpolated; `link` is a key of S (or null).
|
||||
// Each step text is provided per language.
|
||||
var STEPS = {
|
||||
exploring: [
|
||||
{ link: 'journey', en: 'Compare programmes and universities before you settle on a city.', si: 'Primerjajte programe in univerze, preden se odločite za mesto.', mk: 'Споредете програми и универзитети пред да се одлучите за град.' },
|
||||
{ link: 'deadlines', en: 'Check the current application deadlines for {uni}.', si: 'Preverite trenutne prijavne roke za {uni}.', mk: 'Проверете ги тековните рокови за пријавување за {uni}.' },
|
||||
{ link: '{levelPage}', en: 'Read the {levelWord} application overview.', si: 'Preberite pregled prijave na {levelWord} študij.', mk: 'Прочитајте го прегледот за пријавување на {levelWord} студии.' },
|
||||
{ link: null, en: 'Confirm whether any special-status exception applies to you before you rely on the standard pathway.', si: 'Preverite, ali za vas velja katera od izjem s posebnim statusom, preden se zanesete na običajno pot.', mk: 'Потврдете дали за вас важи некој исклучок со посебен статус пред да се потпрете на стандардниот пат.' }
|
||||
],
|
||||
applying: [
|
||||
{ link: '{levelPage}', en: 'Prepare your document package for {uni}.', si: 'Pripravite paket dokumentov za {uni}.', mk: 'Подгответе го пакетот документи за {uni}.' },
|
||||
{ link: 'evs', en: 'Submit your application through eVŠ and save the confirmation.', si: 'Oddajte prijavo prek eVŠ in shranite potrdilo.', mk: 'Поднесете ја пријавата преку eVŠ и зачувајте ја потврдата.' },
|
||||
{ link: 'journey', en: 'Start recognition of your foreign education inside the application.', si: 'Znotraj prijave začnite postopek priznavanja tujega izobraževanja.', mk: 'Во рамките на пријавата започнете го признавањето на странското образование.' },
|
||||
{ link: 'deadlines', en: 'Track the document deadline and result date for {uni}.', si: 'Spremljajte rok za dokumente in datum rezultatov za {uni}.', mk: 'Следете го рокот за документи и датумот на резултати за {uni}.' }
|
||||
],
|
||||
accepted: [
|
||||
{ link: 'journey', en: 'Read the faculty enrolment instructions and complete your enrolment.', si: 'Preberite navodila fakultete za vpis in dokončajte vpis.', mk: 'Прочитајте ги упатствата на факултетот за упис и завршете го уписот.' },
|
||||
{ link: null, en: 'Request your certificate of enrolment (potrdilo o vpisu).', si: 'Zaprosite za potrdilo o vpisu.', mk: 'Побарајте потврда за упис (potrdilo o vpisu).' },
|
||||
{ link: 'journey', en: 'Begin residence, health (RM/SI 3), and housing steps in parallel.', si: 'Vzporedno začnite urejati prebivanje, zdravstvo (RM/SI 3) in nastanitev.', mk: 'Паралелно започнете ги чекорите за престој, здравство (RM/SI 3) и сместување.' },
|
||||
{ link: null, en: 'Arrange accommodation in {city} as early as possible.', si: 'Čim prej uredite nastanitev v mestu {city}.', mk: 'Средете сместување во {city} што е можно поскоро.' }
|
||||
],
|
||||
moving: [
|
||||
{ link: 'journey', en: 'Arrange your temporary residence permit for study before or on arrival.', si: 'Uredite dovoljenje za začasno prebivanje za študij pred prihodom ali ob njem.', mk: 'Средете дозвола за привремен престој за студии пред или при пристигнувањето.' },
|
||||
{ link: null, en: 'Obtain the Macedonian RM/SI 3 health-insurance form where eligible.', si: 'Pridobite makedonski obrazec RM/SI 3 za zdravstveno zavarovanje, če ste upravičeni.', mk: 'Обезбедете го македонскиот образец РМ/СИ 3 за здравствено осигурување ако имате право.' },
|
||||
{ link: null, en: 'Organise accommodation and plan address registration in {city}.', si: 'Uredite nastanitev in načrtujte prijavo prebivališča v mestu {city}.', mk: 'Организирајте сместување и планирајте пријава на адреса во {city}.' },
|
||||
{ link: 'journey', en: 'Pack originals of your education and residence documents in hand luggage.', si: 'V ročno prtljago spravite izvirnike izobraževalnih in bivalnih dokumentov.', mk: 'Спакувајте ги оригиналите од образовните и документите за престој во рачен багаж.' }
|
||||
],
|
||||
arrived: [
|
||||
{ link: null, en: 'Register your address at the administrative unit within the deadline.', si: 'V roku prijavite prebivališče na upravni enoti.', mk: 'Пријавете ја адресата во управната единица во рокот.' },
|
||||
{ link: null, en: 'Submit RM/SI 3 to ZZZS and activate your health insurance.', si: 'Oddajte RM/SI 3 na ZZZS in aktivirajte zdravstveno zavarovanje.', mk: 'Поднесете РМ/СИ 3 до ЗЗЗС и активирајте го здравственото осигурување.' },
|
||||
{ link: null, en: 'Activate student meals and student transport in {city}.', si: 'Aktivirajte študentsko prehrano in študentski prevoz v mestu {city}.', mk: 'Активирајте студентска исхрана и студентски превоз во {city}.' },
|
||||
{ link: 'journey', en: 'Track your residence and insurance expiry dates through the year.', si: 'Skozi leto spremljajte datume poteka prebivanja in zavarovanja.', mk: 'Во текот на годината следете ги датумите на истекување на престојот и осигурувањето.' }
|
||||
]
|
||||
};
|
||||
|
||||
var t = T[lang] || T.en;
|
||||
|
||||
function opt(value, label) {
|
||||
var o = document.createElement('option');
|
||||
o.value = value; o.textContent = label; return o;
|
||||
}
|
||||
function fillSelect(sel, obj, withPick) {
|
||||
if (withPick) sel.appendChild(opt('', t.pick + '…'));
|
||||
Object.keys(obj).forEach(function (k) { sel.appendChild(opt(k, obj[k])); });
|
||||
}
|
||||
|
||||
var selLevel = root.querySelector('[data-role="level"]');
|
||||
var selPhase = root.querySelector('[data-role="phase"]');
|
||||
var selUni = root.querySelector('[data-role="uni"]');
|
||||
var selCity = root.querySelector('[data-role="city"]');
|
||||
var selYear = root.querySelector('[data-role="year"]');
|
||||
var result = root.querySelector('.guide-route-result');
|
||||
|
||||
fillSelect(selLevel, t.levels, true);
|
||||
fillSelect(selPhase, t.phases, true);
|
||||
fillSelect(selUni, t.unis, true);
|
||||
fillSelect(selCity, t.cities, true);
|
||||
[ '2026/2027', '2027/2028' ].forEach(function (y) { selYear.appendChild(opt(y, y)); });
|
||||
|
||||
function esc(s) { return String(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); }
|
||||
|
||||
function build() {
|
||||
var level = selLevel.value, phase = selPhase.value;
|
||||
if (!level || !phase) {
|
||||
result.hidden = false;
|
||||
result.innerHTML = '<p class="guide-route-context">' + esc(t.need) + '</p>';
|
||||
return;
|
||||
}
|
||||
var uniText = selUni.value ? t.unis[selUni.value] : t.yourUni;
|
||||
var cityText = selCity.value ? t.cities[selCity.value] : t.yourCity;
|
||||
var levelWord = t.levels[level].toLowerCase();
|
||||
var levelPage = level === 'master' ? S.master : S.bachelor;
|
||||
|
||||
var ctx = [];
|
||||
ctx.push(t.contextParts.level + ': ' + t.levels[level]);
|
||||
ctx.push(t.contextParts.phase + ': ' + t.phases[phase]);
|
||||
if (selUni.value) ctx.push(t.contextParts.uni + ': ' + t.unis[selUni.value]);
|
||||
if (selCity.value) ctx.push(t.contextParts.city + ': ' + t.cities[selCity.value]);
|
||||
if (selYear.value) ctx.push(t.contextParts.year + ': ' + selYear.value);
|
||||
|
||||
var items = STEPS[phase].map(function (step) {
|
||||
var text = step[lang] || step.en;
|
||||
text = text.replace('{uni}', uniText).replace('{city}', cityText).replace('{levelWord}', levelWord);
|
||||
var linkKey = step.link;
|
||||
if (linkKey === '{levelPage}') linkKey = level === 'master' ? 'master' : 'bachelor';
|
||||
var slug = linkKey && S[linkKey];
|
||||
var li = esc(text);
|
||||
if (slug) {
|
||||
var label = t.link[linkKey] || linkKey;
|
||||
li += ' <a href="' + slug + '/">' + esc(label) + ' →</a>';
|
||||
}
|
||||
return '<li>' + li + '</li>';
|
||||
}).join('');
|
||||
|
||||
result.hidden = false;
|
||||
result.innerHTML =
|
||||
'<h3>' + esc(t.resultHead) + '</h3>' +
|
||||
'<p class="guide-route-context">' + esc(ctx.join(' · ')) + '</p>' +
|
||||
'<ol>' + items + '</ol>';
|
||||
result.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||||
}
|
||||
|
||||
root.querySelector('[data-action="build"]').addEventListener('click', build);
|
||||
root.querySelector('[data-action="reset"]').addEventListener('click', function () {
|
||||
[selLevel, selPhase, selUni, selCity].forEach(function (s) { s.value = ''; });
|
||||
selYear.value = '2026/2027';
|
||||
result.hidden = true; result.innerHTML = '';
|
||||
});
|
||||
})();
|
||||
Reference in new issue
Block a user