Remind members with no recorded preference to opt in

This commit is contained in:
Ian Gulliver
2026-08-20 22:57:50 -07:00
parent 99119dac53
commit c38084a7a4
2 changed files with 89 additions and 18 deletions
+37 -18
View File
@@ -124,6 +124,33 @@ function setChrome(title, backHref) {
} }
} }
const optInForm = 'https://docs.google.com/forms/d/e/1FAIpQLSehrwYXWLJ6LK5_0f5ccdIA1gF0q7jAeDMxV5FWb_Myr4uRog/viewform';
function optInBanner() {
const banner = el('div', 'optin');
const inner = el('div', 'optin-inner container');
inner.append(el('h2', '', 'Help! Opt-In Required'));
inner.append(el('p', '', 'You have not yet opted into the Helios Community Apps and will lose access on Sept 1. Please opt-in. Thank you!'));
const action = el('a', 'optin-button', 'Opt-In');
action.href = optInForm;
action.target = '_blank';
action.rel = 'noopener';
inner.append(action);
banner.append(inner);
return banner;
}
function resetMain(...children) {
const main = document.querySelector('#main');
main.replaceChildren();
const me = byEmail[document.body.dataset.userEmail];
if (me && me.optStatus === 'default') {
main.append(optInBanner());
}
main.append(...children);
return main;
}
function renderNav() { function renderNav() {
const seg = activeSection(); const seg = activeSection();
const nav = document.querySelector('#nav'); const nav = document.querySelector('#nav');
@@ -381,8 +408,7 @@ const tabRenderers = {
}; };
function renderPeople() { function renderPeople() {
const main = document.querySelector('#main'); const main = resetMain();
main.replaceChildren();
const items = peopleTabs.map(t => ({...t, icon: t.key === 'staff' ? 'staff-tab' : t.key})); const items = peopleTabs.map(t => ({...t, icon: t.key === 'staff' ? 'staff-tab' : t.key}));
main.append(tabStrip(items, state.tab, 2, key => { main.append(tabStrip(items, state.tab, 2, key => {
@@ -828,8 +854,7 @@ function familyBand(p, family) {
let personEdit = null; let personEdit = null;
function renderPersonDetail(email) { function renderPersonDetail(email) {
const main = document.querySelector('#main'); const main = resetMain();
main.replaceChildren();
const p = byEmail[email]; const p = byEmail[email];
if (!p) { if (!p) {
main.append(el('div', 'empty', 'Not found.')); main.append(el('div', 'empty', 'Not found.'));
@@ -1048,8 +1073,7 @@ function renderPersonDetail(email) {
} }
function renderFamilyDetail(key) { function renderFamilyDetail(key) {
const main = document.querySelector('#main'); const main = resetMain();
main.replaceChildren();
const family = state.model.families[key]; const family = state.model.families[key];
if (!family) { if (!family) {
main.append(el('div', 'empty', 'Not found.')); main.append(el('div', 'empty', 'Not found.'));
@@ -1322,8 +1346,7 @@ const classroomsTabRenderers = {
}; };
function renderClassroomsPage() { function renderClassroomsPage() {
const main = document.querySelector('#main'); const main = resetMain();
main.replaceChildren();
main.append(tabStrip(classroomsTabs, state.classTab, 1, key => { main.append(tabStrip(classroomsTabs, state.classTab, 1, key => {
state.classTab = key; state.classTab = key;
@@ -1365,8 +1388,7 @@ function renderClassroomsPage() {
} }
function renderStaffPage() { function renderStaffPage() {
const main = document.querySelector('#main'); const main = resetMain();
main.replaceChildren();
const content = el('div', 'content container'); const content = el('div', 'content container');
const header = el('div', 'content-header'); const header = el('div', 'content-header');
@@ -1445,8 +1467,7 @@ function otherFamilyMembers(student) {
} }
function renderRoster(title, image, groups, backLabel) { function renderRoster(title, image, groups, backLabel) {
const main = document.querySelector('#main'); const main = resetMain();
main.replaceChildren();
const from = fromURL(); const from = fromURL();
const back = from && from.pathname === '/classrooms' ? from.pathname + from.search : '/classrooms'; const back = from && from.pathname === '/classrooms' ? from.pathname + from.search : '/classrooms';
main.append(breadcrumbs([['Classrooms', back], [title, null]])); main.append(breadcrumbs([['Classrooms', back], [title, null]]));
@@ -1514,7 +1535,7 @@ function renderRoster(title, image, groups, backLabel) {
function renderGradeDetail(slug) { function renderGradeDetail(slug) {
const grade = state.model.grades.find(g => slugify(g.name) === slug); const grade = state.model.grades.find(g => slugify(g.name) === slug);
if (!grade) { if (!grade) {
document.querySelector('#main').replaceChildren(el('div', 'empty', 'Not found.')); resetMain(el('div', 'empty', 'Not found.'));
return; return;
} }
const students = studentsOf(p => p.grade === grade.name); const students = studentsOf(p => p.grade === grade.name);
@@ -1528,7 +1549,7 @@ function renderGradeDetail(slug) {
function renderClassroomDetail(slug) { function renderClassroomDetail(slug) {
const classroom = state.model.classrooms.find(c => slugify(c.name) === slug); const classroom = state.model.classrooms.find(c => slugify(c.name) === slug);
if (!classroom) { if (!classroom) {
document.querySelector('#main').replaceChildren(el('div', 'empty', 'Not found.')); resetMain(el('div', 'empty', 'Not found.'));
return; return;
} }
const students = studentsOf(p => p.classroom === classroom.name); const students = studentsOf(p => p.classroom === classroom.name);
@@ -1601,8 +1622,7 @@ function emailEntries(tab) {
} }
function renderEmailListPage() { function renderEmailListPage() {
const main = document.querySelector('#main'); const main = resetMain();
main.replaceChildren();
main.append(el('div', 'container email-hint', 'Use the filters to select for specific grades or classrooms.')); main.append(el('div', 'container email-hint', 'Use the filters to select for specific grades or classrooms.'));
@@ -1726,8 +1746,7 @@ const pinIcon = 'data:image/svg+xml;charset=UTF-8,' + encodeURIComponent(
'<circle cx="12" cy="10" r="3" fill="#fff"/></svg>'); '<circle cx="12" cy="10" r="3" fill="#fff"/></svg>');
function renderMapPage() { function renderMapPage() {
const main = document.querySelector('#main'); const main = resetMain();
main.replaceChildren();
const content = el('div', 'content container'); const content = el('div', 'content container');
const header = el('div', 'content-header'); const header = el('div', 'content-header');
+52
View File
@@ -7,6 +7,45 @@
--muted: #707070; --muted: #707070;
--label: #1f4d53; --label: #1f4d53;
--input: #efefef; --input: #efefef;
--alert: #f55e03;
}
.optin {
background: var(--alert);
color: #fff;
}
.optin-inner {
padding-top: 38px;
padding-bottom: 42px;
}
.optin h2 {
margin: 0;
font-size: 44px;
font-weight: 800;
letter-spacing: -0.02em;
}
.optin p {
margin: 14px 0 0;
font-size: 14px;
line-height: 1.5;
color: rgba(255, 255, 255, 0.94);
}
.optin-button {
display: block;
max-width: 492px;
margin: 26px auto 0;
padding: 14px 24px;
border-radius: 10px;
background: #fff;
color: var(--ink);
font-size: 14px;
font-weight: 700;
text-align: center;
text-decoration: none;
} }
* { * {
@@ -1869,3 +1908,16 @@ a.list-row:hover {
height: 62vh; height: 62vh;
} }
} }
@media (max-width: 900px) {
.optin-inner {
padding-top: 26px;
padding-bottom: 28px;
}
.optin h2 {
font-size: 30px;
}
.optin-button {
max-width: none;
}
}