Skip to content

Commit 879c74a

Browse files
Add secondary nav, split clinics by date and status
1 parent baae8d5 commit 879c74a

File tree

16 files changed

+300
-123
lines changed

16 files changed

+300
-123
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.app-count {
2+
@include nhsuk-font(16);
3+
4+
background-color: rgba($color_nhsuk-grey-4, 0.5);
5+
border-radius: nhsuk-spacing(3);
6+
display: inline-block;
7+
min-width: nhsuk-spacing(5);
8+
padding-left: nhsuk-spacing(2);
9+
padding-right: nhsuk-spacing(2);
10+
text-align: center;
11+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
.app-secondary-navigation {
2+
@include nhsuk-responsive-margin(4, "bottom");
3+
}
4+
5+
.app-secondary-navigation__list-item {
6+
margin: 0;
7+
}
8+
9+
.app-secondary-navigation__list-item--current {
10+
border-bottom-width: nhsuk-spacing(1);
11+
}
12+
13+
.app-secondary-navigation__link {
14+
padding-left: nhsuk-spacing(3);
15+
padding-right: nhsuk-spacing(3);
16+
}
17+
18+
// --------
19+
20+
21+
.app-secondary-navigation {
22+
@include nhsuk-font($size: 19);
23+
}
24+
25+
.app-secondary-navigation__link {
26+
@include nhsuk-link-style-default;
27+
@include nhsuk-link-style-no-visited-state;
28+
29+
text-decoration: none;
30+
31+
// Extend the touch area of the link to the list
32+
&::after {
33+
bottom: 0;
34+
content: "";
35+
left: 0;
36+
position: absolute;
37+
right: 0;
38+
top: 0;
39+
}
40+
}
41+
42+
.app-secondary-navigation__list {
43+
@include clearfix;
44+
45+
// The list uses box-shadow rather than a border to set a 1px
46+
// grey line at the bottom, so that border from the current
47+
// item appears on top of the grey line.
48+
box-shadow: inset 0 -1px 0 $nhsuk-border-color;
49+
list-style: none;
50+
margin: 0;
51+
padding: 0;
52+
width: 100%;
53+
}
54+
55+
.app-secondary-navigation__list-item {
56+
box-sizing: border-box;
57+
display: block;
58+
float: left;
59+
margin-right: nhsuk-spacing(4);
60+
padding-bottom: nhsuk-spacing(2);
61+
padding-top: nhsuk-spacing(2);
62+
position: relative;
63+
64+
// More generous padding beneath items on wider screens
65+
@include mq($from: tablet) {
66+
padding-bottom: nhsuk-spacing(3);
67+
}
68+
}
69+
70+
// The last item of the list doesn’t need any spacing to its right.
71+
// Removing this prevents the item from wrapping to the next line
72+
// unnecessarily.
73+
.app-secondary-navigation__list-item:last-child {
74+
margin-right: 0;
75+
}
76+
77+
.app-secondary-navigation__list-item--current {
78+
border-bottom: $nhsuk-border-width solid $color_nhsuk-blue;
79+
padding-bottom: nhsuk-spacing(1);
80+
81+
// More generous padding beneath items on wider screens
82+
@include mq($from: tablet) {
83+
padding-bottom: nhsuk-spacing(2);
84+
}
85+
}
86+
87+
.app-secondary-navigation__list-item--current .app-secondary-navigation__link:link,
88+
.app-secondary-navigation__list-item--current .app-secondary-navigation__link:visited {
89+
color: $nhsuk-text-color;
90+
}

app/assets/sass/main.scss

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
@import 'components/related-nav';
77
@import 'components/header';
88
@import 'components/header-organisation';
9+
@import 'components/secondary-navigation';
10+
@import 'components/count';
11+
912

1013
@import 'typography';
1114
@import 'utils';

app/lib/utils/arrays.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// app/lib/utils/arrays.js
2+
var _ = require('lodash');
3+
24

35
/**
46
* Find an object by ID in an array
@@ -11,6 +13,13 @@ const findById = (array, id) => {
1113
return array.find(item => item.id === id);
1214
};
1315

16+
const push = (array, item) => {
17+
let newArray = [...array]
18+
newArray.push(_.cloneDeep(item)) // clone needed to stop this mutating original
19+
return newArray
20+
}
21+
1422
module.exports = {
23+
push,
1524
findById
1625
};

app/lib/utils/clinics.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// app/lib/utils/clinics.js
2+
const dayjs = require('dayjs');
23

34

45
const config = require('../../config');
@@ -66,9 +67,40 @@ const getClinicHours = (clinic) => {
6667
};
6768
};
6869

70+
/**
71+
* Get clinics filtered by time period
72+
* @param {Array} clinics - Array of all clinics
73+
* @param {string} filter - Filter to apply (today, upcoming, completed, all)
74+
*/
75+
const getFilteredClinics = (clinics, filter = 'all') => {
76+
const today = dayjs().startOf('day');
77+
78+
switch(filter) {
79+
case 'today':
80+
return clinics.filter(clinic =>
81+
dayjs(clinic.date).isSame(today, 'day')
82+
);
83+
84+
case 'upcoming':
85+
return clinics.filter(clinic =>
86+
dayjs(clinic.date).isAfter(today, 'day')
87+
).sort((a, b) => new Date(a.date) - new Date(b.date));
88+
89+
case 'completed':
90+
return clinics.filter(clinic =>
91+
dayjs(clinic.date).isBefore(today, 'day')
92+
).sort((a, b) => new Date(b.date) - new Date(a.date)); // Most recent first
93+
94+
case 'all':
95+
default:
96+
return [...clinics].sort((a, b) => new Date(a.date) - new Date(b.date));
97+
}
98+
};
99+
69100

70101
module.exports = {
71102
getTodaysClinics,
103+
getFilteredClinics,
72104
getClinicEvents,
73105
formatTimeSlot,
74106
getClinicHours

app/routes/clinics.js

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// app/routes/clinics.js
22

33
const dayjs = require('dayjs');
4+
const { getFilteredClinics, getClinicEvents } = require('../lib/utils/clinics');
45

56
/**
67
* Get clinic and its related data from id
@@ -36,8 +37,47 @@ function getClinicData(data, clinicId) {
3637

3738
module.exports = router => {
3839

39-
router.get('/clinics/today', (req, res) => {
40-
res.render('clinics/today');
40+
router.get('/clinics', (req, res) => {
41+
res.redirect('/clinics/today');
42+
});
43+
44+
const clinicViews = ['/clinics/today', '/clinics/upcoming', '/clinics/completed', '/clinics/all'];
45+
46+
router.get(clinicViews, (req, res) => {
47+
48+
const data = req.session.data
49+
50+
// Extract filter from the URL path
51+
let filter = req.path.split('/').pop();
52+
53+
// Check filter from either URL param or query string
54+
filter = filter || req.query.filter || 'all';
55+
56+
// Add additional data needed for each clinic
57+
const clinicsWithData = data.clinics.map(clinic => {
58+
const unit = data.breastScreeningUnits.find(u => u.id === clinic.breastScreeningUnitId);
59+
const location = unit.locations.find(l => l.id === clinic.locationId);
60+
const events = getClinicEvents(data.events, clinic.id);
61+
62+
return {
63+
...clinic,
64+
unit,
65+
location,
66+
events
67+
};
68+
});
69+
70+
// Get filtered clinics
71+
const filteredClinics = getFilteredClinics(clinicsWithData, filter);
72+
73+
res.render('clinics/index', {
74+
filter,
75+
clinics: clinicsWithData,
76+
filteredClinics,
77+
formatDate: (date) => dayjs(date).format('D MMMM YYYY')
78+
});
79+
80+
4181
});
4282

4383
// View participant within clinic context
@@ -54,12 +94,7 @@ module.exports = router => {
5494
return;
5595
}
5696

57-
res.render('participants/show', {
58-
participant,
59-
clinic,
60-
event,
61-
clinicId: req.params.clinicId,
62-
participantId: req.params.participantId
97+
res.render('clinics.index', {
6398
});
6499
});
65100

@@ -96,15 +131,14 @@ module.exports = router => {
96131
return res.redirect(`/clinics/${req.params.id}`);
97132
}
98133

99-
console.log(`Events before: ${clinicData.events.length}`)
100134
const filteredEvents = filterEvents(clinicData.events, filter);
101-
console.log(`Events after: ${filteredEvents.length}`)
102135

103136
res.render('clinics/show', {
104137
clinicId: req.params.id,
105138
clinic: clinicData.clinic,
106139
allEvents: clinicData.events,
107140
filteredEvents: filteredEvents,
141+
status: filter,
108142
unit: clinicData.unit,
109143
currentFilter: filter,
110144
formatDate: (date) => dayjs(date).format('D MMMM YYYY'),
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{% macro appCount(number) -%}
2+
{%- include './template.njk' -%}
3+
{%- endmacro %}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<span class="app-count">
2+
<span class="nhsuk-u-visually-hidden">(</span>
3+
{{- number -}}
4+
<span class="nhsuk-u-visually-hidden">)</span>
5+
</span>
6+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{% macro appSecondaryNavigation(params) %}
2+
{%- include "./template.njk" -%}
3+
{% endmacro %}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<nav class="app-secondary-navigation {%- if params.classes %} {{ params.classes }}{% endif -%}" {% if params.labelledBy %}aria-labelledby="{{ params.labelledBy }}"{% else %}aria-label="{{ params.visuallyHiddenTitle or "Secondary menu" }}"{% endif %} {%- for attribute, value in params.attributes %} {{ attribute }}="{{ value }}"{% endfor %}>
2+
<ul class="app-secondary-navigation__list">
3+
{% for item in params.items %}
4+
{% if item %}
5+
<li class="app-secondary-navigation__list-item {{ "app-secondary-navigation__list-item--current" if item.current }}{% if item.classes %} {{ item.classes }}{% endif -%}">
6+
<a class="app-secondary-navigation__link" href="{{ item.href }}" {{ "aria-current=page" if item.current }}>
7+
{{ item.text }}
8+
</a>
9+
</li>
10+
{% endif %}
11+
{% endfor %}
12+
</ul>
13+
</nav>

0 commit comments

Comments
 (0)