You may or may not be able to help, but I’m doing a free website for a low socio-economic rural school and I want to have a dynamic text field on the home page to help parents to know where we are at in the school year.
IT IS WEEK {X} of TERM {X}. THERE ARE {X} WEEKS UNTIL THE {MONTH} SCHOOL HOLIDAYS
Put the terms in a CMS collection. Enter the start and end dates.
On your home page, put a collection list bound to terms, filtered to show only terms that started before today, and end after today. That’s the current term. Limit to 1, to be sure.
In that collection list, drop an HTML embed. have it emit your start and end dates from the term, e.g.
<data id="term-dates" start="(start date field)" end="(end date field)"></data>
Add a script that finds that data by ID, gets the fields, and converts them to Dates. now you’ve got the start and end date of the current term, and the school can manage the term dates themselves, and adjust them whenever needed.
The actual weeks-between-dates calc is just JS, you’ll find lots of functions online for this. moment.js is a good toolset to do date math too.
Hi @Hayden_Judd1 as this request is not possible to solve in writing here is a 20min video where I try to explain what issues you may face and how it can be solved.
here is the code I have used in the video
for WEBFLOW to create an array of objects from CMS
// create WF collection eg: school terms
// add title as text files
// add start date as a date field
// add end date as a date field
// in page add collection and in collection item add these 3 fields
const shoolYearTermsArray = [];
const terms = Array.from(document.querySelectorAll('.term')) as Array<HTMLElement>;
terms.forEach((term) => {
const termName = term.querySelector('.term-name')?.textContent;
const termStart = term.querySelector('.term-start')?.textContent;
const termEnd = term.querySelector('.term-end')?.textContent;
if (termName && termStart && termEnd) {
shoolYearTermsArray.push({
term: termName,
start: termStart,
end: termEnd
});
}
});
Rest of JS
// dayJS
import dayjs from 'dayjs';
import weekOfYear from 'dayjs/plugin/weekOfYear';
dayjs.extend(weekOfYear);
// fake db
const shoolYearTerms = [
{
name: 'February mid-term break',
start: '2023-02-14',
end: '2023-02-18'
},
{
name: 'Easter',
start: '2023-04-04',
end: '2023-04-18'
},
{
name: 'Autumn mid-name break',
start: '2023-10-31',
end: '2023-11-04'
},
{
name: 'Christmas',
start: '2023-12-20',
end: '2024-01-04'
}
];
// fake date
// const fakeDate = '2023-12-24';
// const currDate = dayjs(fakeDate).format('YYYY-MM-DD');
// dayJS
const currDate = dayjs().format('YYYY-MM-DD');
const currYear = dayjs(currDate).year();
const weekNumber = dayjs().week();
// functions returns
const nextNearestTerm = followingTerm(shoolYearTerms, currDate); //?
const currrentTerm = findTerms(shoolYearTerms, currDate); //?
const daysToNextTerm = dayjs(nextNearestTerm.start).diff(currDate, 'day');
// find current school term
function findTerms(shoolYearTerms: Array<Record<string, string >>, currDate: string) {
let currentSchoolTerm: Record<string, string> = {};
for (const term of shoolYearTerms) {
const termStartDay = dayjs(term.start).format('YYYY-MM-DD');
const termEndsDay = dayjs(term.end).format(`YYYY-MM-DD`);
if (dayjs(termStartDay).year() === currYear && dayjs(termEndsDay).year() === currYear) {
if (termStartDay <= currDate && termEndsDay >= currDate) {
currentSchoolTerm = term;
break;
}
}
if (dayjs(termStartDay).year() === currYear && dayjs(termEndsDay).year() === currYear + 1) {
if (termStartDay <= currDate && termEndsDay >= currDate) {
currentSchoolTerm = term;
break;
}
}
}
return currentSchoolTerm;
}
// find following school term
function followingTerm(shoolYearTerms: Array<Record<string, string>>, currDate: string) {
let nextClosestTerm: Record<string, string> = {};
for (const [i, term] of shoolYearTerms.entries()) {
const termStartDay = dayjs(term.start).format(`YYYY-MM-DD`);
const termEndsDay = dayjs(term.end).format(`YYYY-MM-DD`);
if (
dayjs(termStartDay).year() === currYear &&
dayjs(termEndsDay).year() === currYear &&
i !== shoolYearTerms.length - 1
) {
if (termStartDay >= currDate && termEndsDay >= currDate) {
nextClosestTerm = term;
break;
}
}
// Recurring part
if (
(dayjs(termStartDay).year() === currYear && dayjs(termEndsDay).year() !== currYear) ||
i === shoolYearTerms.length - 1
) {
if (termStartDay >= currDate && currDate >= termEndsDay) {
nextClosestTerm = term; //?
break;
}
} else {
// when term active increase next term year by 1 and reset is on current year when term ends
shoolYearTerms[0].start = dayjs(shoolYearTerms[0].start).format(`${currYear + 1}-MM-DD`);
shoolYearTerms[0].end = dayjs(shoolYearTerms[0].end).format(`${currYear + 1}-MM-DD`);
nextClosestTerm = shoolYearTerms[0];
}
}
return nextClosestTerm;
}
// message code example
function message(weekNumber: number, currrentTerm: any, daysToNextTerm: number) {
return `Is week ${weekNumber} of the ${currYear}.${ifCurrntTermIsNotSet(
currrentTerm
)} and there ${substr(daysToNextTerm)} to ${nextNearestTerm.name} `;
}
function ifCurrntTermIsNotSet(currrentTerm: any) {
if (currrentTerm === null || undefined) {
return 'There is no school term at the moment';
}
return ` We are currently in ${currrentTerm.name} term`;
}
function substr(days: number) {
if (Number(days) > 1 && Number(days) <= 7) {
return `are ${days} days`;
}
if (Number(days) > 7) {
return `are ${Math.floor(days / 7)} weeks`;
}
return `is ${days} day`;
}
const msgToDisplay = message(weekNumber, currrentTerm, daysToNextTerm);
console.log(msgToDisplay);
as this is only the first raw code that works there is still space for refactoring
I have found a bug in the findNextTerm function I didn’t realize it when publishing it at 3:00 AM . This function works in sequential order instead of returning the nearest term date related to the current date.
When I will have time I will fix it.
EDIT:
Hi @Hayden_Judd1 once you will come to this forum to look if someone trying to help. I have fixed and updated the code above. Now it should be recurring.