From 2a8c48a18445588dcfbbdaa02ab2b52cebc2a658 Mon Sep 17 00:00:00 2001 From: Caitlin Roach Date: Tue, 16 Jun 2026 16:14:41 +0100 Subject: [PATCH 1/4] Add empty state for no pharmacies --- app/routes/prototype-admin.js | 14 +++ .../includes/_preset-scenarios-table.html | 8 ++ app/views/pharmacies/index.html | 116 +++++++++--------- 3 files changed, 81 insertions(+), 57 deletions(-) diff --git a/app/routes/prototype-admin.js b/app/routes/prototype-admin.js index b2401748..2bd6777f 100644 --- a/app/routes/prototype-admin.js +++ b/app/routes/prototype-admin.js @@ -564,6 +564,20 @@ module.exports = (router) => { res.redirect('/home') }) + // ---------------------------------------------------------------- + // Preset: Pharmacy HQ, no data (Amanda White, P15951) + // ---------------------------------------------------------------- + + router.get('/prototype-setup/preset/pharmacy-hq-no-data', (req, res) => { + resetSession(req) + const data = req.session.data + data.currentUserId = '6424325235325' + data.currentOrganisationId = 'P15951' + // Remove all pharmacies belonging to P15951 to start with a clean slate + data.organisations = data.organisations.filter(org => org.companyId !== 'P15951' || org.type === 'Pharmacy HQ') + res.redirect('/home') + }) + // ---------------------------------------------------------------- // Preset: Recorder, single organisation (Ocean Merritt, FR4V56) // ---------------------------------------------------------------- diff --git a/app/views/includes/_preset-scenarios-table.html b/app/views/includes/_preset-scenarios-table.html index 3d9bd63b..05a98cf7 100644 --- a/app/views/includes/_preset-scenarios-table.html +++ b/app/views/includes/_preset-scenarios-table.html @@ -71,6 +71,14 @@ role: "Group administrator", scenarioDetails: "Group admin for a large pharmacy chain (same-name pharmacies)." }, + { + presetLabel: "Group admin, pharmacy HQ (no data)", + presetPath: "/prototype-setup/preset/pharmacy-hq-no-data", + userName: "Amanda White", + userEmail: "amanda.white@nhs.net", + role: "Group administrator", + scenarioDetails: "Group admin for a pharmacy HQ with no pre-loaded data, pharmacies or users." + }, { presetLabel: "Regional lead", presetPath: "/prototype-setup/preset/regions", diff --git a/app/views/pharmacies/index.html b/app/views/pharmacies/index.html index b033a9bf..ac9ab6ff 100644 --- a/app/views/pharmacies/index.html +++ b/app/views/pharmacies/index.html @@ -43,65 +43,67 @@

Pharmacies

href: "/pharmacies/select" }) }} - - -
Pharmacies added ({{ organisations | length }})
- {% if (organisations | length) > 10 %} -
- - -
- {% endif %} - - - - - - - - - - - - {% for organisation in organisations %} - - - - - - + {% if (organisations | length) > 0 %} +
- Name - - Vaccines - - Users - - Status - - Actions -
- {{ organisation.name }} ({{ organisation.id}}) - - {% set vaccinesEnabled = [] %} - {% for vaccine in organisation.vaccines %} - {% if vaccine.status == "enabled" %} - {% set vaccinesEnabled = (vaccinesEnabled.push(vaccine.name), vaccinesEnabled) %} - {% endif %} - {% endfor %} - - {{ (vaccinesEnabled | sort | join(", ")) | capitaliseFirstLetter }} - - {{ organisationUserCounts[organisation.id] }} - - {{ organisation.status }} - - Manage -
+ +
Pharmacies added ({{ organisations | length }})
+ {% if (organisations | length) > 10 %} +
+ + +
+ {% endif %} + + + + + + + + - {% endfor %} + + + {% for organisation in organisations %} + + + + + + + + {% endfor %} - -
+ Name + + Vaccines + + Users + + Status + + Actions +
+ {{ organisation.name }} ({{ organisation.id}}) + + {% set vaccinesEnabled = [] %} + {% for vaccine in organisation.vaccines %} + {% if vaccine.status == "enabled" %} + {% set vaccinesEnabled = (vaccinesEnabled.push(vaccine.name), vaccinesEnabled) %} + {% endif %} + {% endfor %} + + {{ (vaccinesEnabled | sort | join(", ")) | capitaliseFirstLetter }} + + {{ organisationUserCounts[organisation.id] }} + + {{ organisation.status }} + + Manage +
+ + + {% endif %} {% if closedOrganisations.length > 0 %}
From 8644be101b23b98320c5bfc5df342c0657264141 Mon Sep 17 00:00:00 2001 From: Caitlin Roach Date: Tue, 4 Aug 2026 15:03:57 +0100 Subject: [PATCH 2/4] Updates to vaccine product page and active/deactivate batch pages --- app/routes/record-vaccinations.js | 2 +- app/routes/vaccines.js | 54 ++++-- ...plete-batch.html => deactivate-batch.html} | 8 +- app/views/vaccines/product-page.html | 167 +++++++++++++----- app/views/vaccines/reactivate.html | 27 ++- 5 files changed, 185 insertions(+), 73 deletions(-) rename app/views/vaccines/{deplete-batch.html => deactivate-batch.html} (78%) diff --git a/app/routes/record-vaccinations.js b/app/routes/record-vaccinations.js index 1e20ad7f..5ad39340 100644 --- a/app/routes/record-vaccinations.js +++ b/app/routes/record-vaccinations.js @@ -846,7 +846,7 @@ module.exports = router => { return (expiryDate > dateToday) }) - .filter((batch) => !batch.depletedDate) + .filter((batch) => !batch.deactivatedDate) if (req.query.showError === 'yes') { diff --git a/app/routes/vaccines.js b/app/routes/vaccines.js index 1ed8a0f0..8b81cf6c 100644 --- a/app/routes/vaccines.js +++ b/app/routes/vaccines.js @@ -184,7 +184,11 @@ module.exports = (router) => { router.get('/vaccines/:id', (req, res) => { const data = req.session.data const perPage = 20; // Max number of users to show per page - const page = parseInt(req.query.page) || 1 ; // Current page, default to 1 + const queryPage = parseInt(req.query.page) || 1 ; // Current page, default to 1 + const tab = (req.query.tab || 'active').toLowerCase() + const deactivated = req.query.deactivated === 'true' + const reactivated = req.query.reactivated === 'true' + const updatedBatchNumber = req.query.batchNumber const vaccine = data.vaccineStock.find((vaccine) => vaccine.id === req.params.id) if (!vaccine) { res.redirect('/vaccines'); return } @@ -194,6 +198,8 @@ module.exports = (router) => { const site = currentOrganisation.sites.find((site) => site.id === vaccine.siteId) const today = new Date().toISOString().substring(0,10) + const validTabs = ['active', 'inactive'] + const currentTab = validTabs.includes(tab) ? tab : 'active' const allBatches = vaccine.batches.sort((a, b) => { const expiryA = a.expiryDate @@ -207,11 +213,21 @@ module.exports = (router) => { return 0; }) - const totalBatches = allBatches.length - const indexStartFrom = (page - 1) * perPage - const totalPages = Math.ceil(totalBatches / perPage) + const isActiveBatch = (batch) => { + return !batch.deactivatedDate && batch.expiryDate >= today + } - const batches = allBatches.slice(indexStartFrom, indexStartFrom + perPage) + const batchesByStatus = { + active: allBatches.filter((batch) => isActiveBatch(batch)), + inactive: allBatches.filter((batch) => !isActiveBatch(batch)) + } + + const filteredBatches = batchesByStatus[currentTab] + const totalBatches = filteredBatches.length + const totalPages = Math.ceil(totalBatches / perPage) + const page = totalPages > 0 ? Math.min(queryPage, totalPages) : 1 + const indexStartFrom = (page - 1) * perPage + const batches = filteredBatches.slice(indexStartFrom, indexStartFrom + perPage) res.render('vaccines/product-page', { @@ -221,7 +237,13 @@ module.exports = (router) => { today, totalPages, totalBatches, - page + page, + currentTab, + activeBatchesCount: batchesByStatus.active.length, + inactiveBatchesCount: batchesByStatus.inactive.length, + deactivated, + reactivated, + updatedBatchNumber }) }) @@ -301,8 +323,8 @@ module.exports = (router) => { res.redirect('/vaccines/' + vaccine.id) }) - // View page to deplete a batch - router.get('/vaccines/:vaccineId/:batchNumber/deplete', (req, res) => { + // View page to deactivate a batch + router.get('/vaccines/:vaccineId/:batchNumber/deactivate', (req, res) => { const data = req.session.data const vaccine = data.vaccineStock.find((vaccine) => vaccine.id === req.params.vaccineId) if (!vaccine) { res.redirect('/vaccines'); return } @@ -313,25 +335,25 @@ module.exports = (router) => { const batch = vaccine.batches.find((batch) => batch.batchNumber === req.params.batchNumber) if (!batch) { res.redirect(`/vaccines/${vaccine.id}`); return } - res.render('vaccines/deplete-batch', { + res.render('vaccines/deactivate-batch', { vaccine, site, batch }) }) - // Mark batch as depleted - router.post('/vaccines/:vaccineId/:batchNumber/depleted', (req, res) => { + // Mark batch as deactivated + router.post('/vaccines/:vaccineId/:batchNumber/deactivated', (req, res) => { const data = req.session.data const vaccine = data.vaccineStock.find((vaccine) => vaccine.id === req.params.vaccineId) if (!vaccine) { res.redirect('/vaccines'); return } const batch = vaccine.batches.find((batch) => batch.batchNumber === req.params.batchNumber) - let depletedDate = new Date() + let deactivatedDate = new Date() - batch.depletedDate = depletedDate.toISOString().substring(0,10) + batch.deactivatedDate = deactivatedDate.toISOString().substring(0,10) - res.redirect('/vaccines/' + vaccine.id) + res.redirect(`/vaccines/${vaccine.id}?tab=inactive&deactivated=true&batchNumber=${encodeURIComponent(batch.batchNumber)}`) }) @@ -362,8 +384,8 @@ module.exports = (router) => { if (!vaccine) { res.redirect('/vaccines'); return } const batch = vaccine.batches.find((batch) => batch.batchNumber === req.params.batchNumber) - batch.depletedDate = null + batch.deactivatedDate = null - res.redirect('/vaccines/' + vaccine.id) + res.redirect(`/vaccines/${vaccine.id}?tab=active&reactivated=true&batchNumber=${encodeURIComponent(batch.batchNumber)}`) }) } diff --git a/app/views/vaccines/deplete-batch.html b/app/views/vaccines/deactivate-batch.html similarity index 78% rename from app/views/vaccines/deplete-batch.html rename to app/views/vaccines/deactivate-batch.html index 869f1021..eaf55e67 100644 --- a/app/views/vaccines/deplete-batch.html +++ b/app/views/vaccines/deactivate-batch.html @@ -1,6 +1,6 @@ {% extends 'layout.html' %} -{% set pageName = "Deplete batch" %} +{% set pageName = "Deactivate batch" %} {% set currentSection = "vaccines" %} @@ -34,13 +34,13 @@

{{ pageName }}

} ] }) }} -

Depleted batches will be made unavailable.

+

Deactivated batches will be made unavailable immediately. Batches can be reactivated if needed.

-
+ {{ button({ - "text": "Confirm deplete batch" + "text": "Confirm deactivate batch" }) }}
diff --git a/app/views/vaccines/product-page.html b/app/views/vaccines/product-page.html index ad970ffe..6a708b9d 100644 --- a/app/views/vaccines/product-page.html +++ b/app/views/vaccines/product-page.html @@ -16,6 +16,34 @@
+ {% if deactivated %} + {% set html %} +

+ Batch deactivated +

+

{{ ("Batch " + updatedBatchNumber + " has been deactivated.") if updatedBatchNumber else "Batch has been deactivated." }}

+ {% endset %} + + {{ notificationBanner({ + html: html, + type: "success" + }) }} + {% endif %} + + {% if reactivated %} + {% set html %} +

+ Batch reactivated +

+

{{ ("Batch " + updatedBatchNumber + " has been reactivated.") if updatedBatchNumber else "Batch has been reactivated." }}

+ {% endset %} + + {{ notificationBanner({ + html: html, + type: "success" + }) }} + {% endif %} +

{{ vaccine.vaccineProduct }}

{{ summaryList({ @@ -60,9 +88,37 @@

{{ vaccine.vaccineProduct }}

+

Batches

+ + {% set activeCount = activeBatchesCount | default(0) %} + {% set inactiveCount = inactiveBatchesCount | default(0) %} + + {{ appSecondaryNavigation({ + visuallyHiddenTitle: "Batches by status", + items: [{ + text: "Active (" + activeCount + ")", + href: "/vaccines/" + vaccine.id + "?tab=active", + current: (currentTab == "active") + }, { + text: "Inactive (" + inactiveCount + ")", + href: "/vaccines/" + vaccine.id + "?tab=inactive", + current: (currentTab == "inactive") + }] + }) }} - - + {% set columns = 2 %} + {% if currentTab == "inactive" %} + {% set columns = columns + 2 %} + {% endif %} + {% if vaccine.vaccineProduct == "Spikevax JN.1" %} + {% set columns = columns + 1 %} + {% endif %} + {% if site.status != "closed" %} + {% set columns = columns + 1 %} + {% endif %} + + +
Batches
- - - - + {% if currentTab == "inactive" %} + + + {% endif %} {% if site.status != "closed" %} @@ -93,48 +148,62 @@

{{ vaccine.vaccineProduct }}

- {% for batch in batches %} + {% if (batches | length) == 0 %} - - {% if vaccine.vaccineProduct == "Spikevax JN.1" %} + + {% else %} + {% for batch in batches %} + - {% endif %} - - - {% endif %} - - {% if site.status != "closed" %} - - {% endif %} + {% if currentTab == "inactive" %} + + + {% endif %} + {% if site.status != "closed" %} + + {% endif %} - - {% endfor %} + + {% endfor %} + {% endif %}
@@ -76,15 +132,14 @@

{{ vaccine.vaccineProduct }}

Expiry date - Status - - Depleted date - - + Date deactivated + + Reason deactivated +
- {{ batch.batchNumber }} + + No {{ currentTab }} batches found.
- {{ batch.packType }} + {{ batch.batchNumber }} - {{ batch.expiryDate | govukDate }} - - {% if batch.depletedDate %} - {{ tag({text: "Depleted", classes: "nhsuk-tag--grey" }) }} - {% elif (batch.expiryDate | daysAgo) > 0 %} - {{ tag({text: "Expired", classes: "nhsuk-tag--grey" }) }} - {% else %} - {{ tag({text: "Active" }) }} - {% endif %} - - {% if batch.depletedDate %} - {{ batch.depletedDate | govukDate }} + {% if vaccine.vaccineProduct == "Spikevax JN.1" %} + + {{ batch.packType }} + {% if (batch.expiryDate | daysAgo) > 0 %} {% else %} - Edit{{ batch.batchNumber }} -   - {% if batch.depletedDate %} - Reactivate{{ batch.batchNumber }} - {% else %} - Deplete{{ batch.batchNumber }} - {% endif %} - {% endif %} + + {{ batch.expiryDate | govukDate }} + {% if batch.deactivatedDate %} + {{ batch.deactivatedDate | govukDate }} + {% else %} + {{ batch.expiryDate | govukDate }} + {% endif %} + + {% if batch.deactivatedDate %} + Deactivated by user + {% elif (batch.expiryDate | daysAgo) > 0 %} + Expired + {% endif %} + + {% if currentTab == "inactive" %} + {% if batch.deactivatedDate %} + Reactivate{{ batch.batchNumber }} + {% endif %} + {% else %} + {% if (batch.expiryDate | daysAgo) > 0 %} + {% else %} + Edit{{ batch.batchNumber }} +   + Deactivate{{ batch.batchNumber }} + {% endif %} + {% endif %} +
@@ -143,7 +212,7 @@

{{ vaccine.vaccineProduct }}

{% for i in range(1, totalPages + 1) -%} {% set items = (items.push({ number: i, - href: "/vaccines/" + vaccine.id + "?page=" + i, + href: "/vaccines/" + vaccine.id + "?tab=" + currentTab + "&page=" + i, current: (i === page) }), items) %} {%- endfor %} @@ -152,10 +221,10 @@

{{ vaccine.vaccineProduct }}

{% if totalPages > 0 %} {{ pagination({ previous: { - href: "/vaccines/" + vaccine.id + "?page=" + (page - 1) if page != 1 + href: "/vaccines/" + vaccine.id + "?tab=" + currentTab + "&page=" + (page - 1) if page != 1 }, next: { - href: "/vaccines/" + vaccine.id + "?page=" + (page + 1) if page != totalPages + href: "/vaccines/" + vaccine.id + "?tab=" + currentTab + "&page=" + (page + 1) if page != totalPages }, items: items }) }} diff --git a/app/views/vaccines/reactivate.html b/app/views/vaccines/reactivate.html index 72c54fdc..507b7737 100644 --- a/app/views/vaccines/reactivate.html +++ b/app/views/vaccines/reactivate.html @@ -1,6 +1,6 @@ {% extends 'layout.html' %} -{% set pageName = "Reactivate batch " + batch.batchNumber %} +{% set pageName = "Reactivate batch" %} {% set currentSection = "vaccines" %} @@ -14,12 +14,33 @@

{{ pageName }}

-

This batch will become ‘active’ immediately.

+ {{ summaryList({ + rows: [ + { + key: { + text: "Batch number" + }, + value: { + text: batch.batchNumber + } + }, + { + key: { + text: "Expiry date" + }, + value: { + text: batch.expiryDate | govukDate + } + } + ] + }) }} + +

Reactivated batches will become available immediately.

{{ button({ - text: "Reactivate" + text: "Confirm reactivate batch" })}}
From f80d68ad6a138ded2e75255610dd6031bbe219b7 Mon Sep 17 00:00:00 2001 From: Caitlin Roach Date: Wed, 5 Aug 2026 10:15:48 +0100 Subject: [PATCH 3/4] Added new flow for when a user tries to add an already existing but deactivated batch --- app/routes/vaccines.js | 22 +++++++++++- .../vaccines/add-batch-to-site-check.html | 35 +++++++++++++++---- app/views/vaccines/product-page.html | 2 +- 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/app/routes/vaccines.js b/app/routes/vaccines.js index 8b81cf6c..1693e1cb 100644 --- a/app/routes/vaccines.js +++ b/app/routes/vaccines.js @@ -140,7 +140,6 @@ module.exports = (router) => { // Viewing check answers page router.get('/vaccines/check', (req, res) => { - const data = req.session.data const siteId = data.siteId @@ -164,6 +163,15 @@ module.exports = (router) => { const expiryDate = new Date(data.batchExpiryDate.year, (parseInt(data.batchExpiryDate.month) - 1), data.batchExpiryDate.day, 12).toISOString().substring(0,10) + const matchingDeactivatedBatch = vaccine.batches.find((batch) => { + return batch.batchNumber === data.batchNumber && batch.expiryDate === expiryDate && batch.deactivatedDate + }) + + if (matchingDeactivatedBatch) { + res.redirect(`/vaccines/${vaccine.id}/add-batch-check`) + return + } + vaccine.batches.push({ id: generatedId, batchNumber: data.batchNumber, @@ -273,9 +281,21 @@ module.exports = (router) => { const site = currentOrganisationSites.find((site) => site.id == vaccine.siteId) + let matchingDeactivatedBatch + const { day, month, year } = data.batchExpiryDate || {} + + if (data.batchNumber && day && month && year) { + const expiryDate = new Date(year, (parseInt(month) - 1), day, 12).toISOString().substring(0,10) + + matchingDeactivatedBatch = vaccine.batches.find((batch) => { + return batch.batchNumber === data.batchNumber && batch.expiryDate === expiryDate && batch.deactivatedDate + }) + } + res.render('vaccines/add-batch-to-site-check', { vaccine, site, + matchingDeactivatedBatch, }) }) diff --git a/app/views/vaccines/add-batch-to-site-check.html b/app/views/vaccines/add-batch-to-site-check.html index 0d0650d4..410d9868 100644 --- a/app/views/vaccines/add-batch-to-site-check.html +++ b/app/views/vaccines/add-batch-to-site-check.html @@ -18,6 +18,18 @@

Check and confirm

+ {% if matchingDeactivatedBatch %} + {% set html %} +

Batch already exists

+

Batch {{ matchingDeactivatedBatch.batchNumber }} with expiry date {{ matchingDeactivatedBatch.expiryDate | govukDate }} already exists and is deactivated.

+

You can reactivate this batch instead of adding it again.

+ {% endset %} + + {{ notificationBanner({ + html: html + }) }} + {% endif %} + {{ summaryList({ classes: "nhsuk-u-margin-bottom-2", @@ -101,15 +113,26 @@

Check and confirm

] }) }} -

Edit batch

+ {% if not matchingDeactivatedBatch %} +

Edit batch

+ {% endif %} -
- {{ button({ - "text": "Confirm" - }) }} -
+ {% if matchingDeactivatedBatch %} +
+ {{ button({ + text: "Reactivate batch", + classes: "nhsuk-u-margin-top-6" + }) }} +
+ {% else %} +
+ {{ button({ + "text": "Confirm" + }) }} +
+ {% endif %}
diff --git a/app/views/vaccines/product-page.html b/app/views/vaccines/product-page.html index 6a708b9d..118fd69a 100644 --- a/app/views/vaccines/product-page.html +++ b/app/views/vaccines/product-page.html @@ -218,7 +218,7 @@

Batches {%- endfor %} - {% if totalPages > 0 %} + {% if totalBatches > 20 %} {{ pagination({ previous: { href: "/vaccines/" + vaccine.id + "?tab=" + currentTab + "&page=" + (page - 1) if page != 1 From b7febc97e4afcbe12a3d585ffbd6a59a64cf1a4a Mon Sep 17 00:00:00 2001 From: Caitlin Roach Date: Wed, 5 Aug 2026 10:30:10 +0100 Subject: [PATCH 4/4] Added ability to deactivate and reactivate sites --- app/routes/vaccines.js | 62 +++++++++++++++++++- app/views/vaccines/deactivate-site.html | 28 +++++++++ app/views/vaccines/index.html | 77 +++++++++++++++++++++++-- app/views/vaccines/reactivate-site.html | 27 +++++++++ 4 files changed, 189 insertions(+), 5 deletions(-) create mode 100644 app/views/vaccines/deactivate-site.html create mode 100644 app/views/vaccines/reactivate-site.html diff --git a/app/routes/vaccines.js b/app/routes/vaccines.js index 1693e1cb..666477df 100644 --- a/app/routes/vaccines.js +++ b/app/routes/vaccines.js @@ -3,6 +3,12 @@ module.exports = (router) => { router.get('/vaccines', (req, res) => { const currentOrganisation = res.locals.currentOrganisation const data = req.session.data + const deactivatedSite = req.query.deactivatedSite === 'true' + const reactivatedSite = req.query.reactivatedSite === 'true' + const siteName = req.query.siteName + const siteTab = (req.query.siteTab || 'active').toLowerCase() + const validSiteTabs = ['active', 'deactivated'] + const currentSiteTab = validSiteTabs.includes(siteTab) ? siteTab : 'active' const organisationVaccines = res.locals.currentOrganisation.vaccines || [] @@ -18,10 +24,20 @@ module.exports = (router) => { .map((vaccine) => vaccine.name) const vaccineStock = data.vaccineStock.filter((vaccine) => vaccine.organisationId === currentOrganisation.id) + const siteIdsInUse = [...new Set(vaccineStock.map((vaccine) => vaccine.siteId))] + const sitesInUse = (currentOrganisation.sites || []).filter((site) => siteIdsInUse.includes(site.id)) + const activeSitesCount = sitesInUse.filter((site) => site.status !== 'closed').length + const deactivatedSitesCount = sitesInUse.filter((site) => site.status === 'closed').length res.render('vaccines/index', { vaccineStock, - vaccinesThatCanBeRequested + vaccinesThatCanBeRequested, + deactivatedSite, + reactivatedSite, + siteName, + currentSiteTab, + activeSitesCount, + deactivatedSitesCount }) }) @@ -152,6 +168,50 @@ module.exports = (router) => { }) }) + // View page to deactivate a site + router.get('/vaccines/sites/:siteId/deactivate', (req, res) => { + const currentOrganisationSites = res.locals.currentOrganisation.sites || [] + const site = currentOrganisationSites.find((item) => item.id === req.params.siteId) + if (!site) { res.redirect('/vaccines'); return } + + res.render('vaccines/deactivate-site', { + site + }) + }) + + // Mark site as closed + router.post('/vaccines/sites/:siteId/deactivated', (req, res) => { + const currentOrganisationSites = res.locals.currentOrganisation.sites || [] + const site = currentOrganisationSites.find((item) => item.id === req.params.siteId) + if (!site) { res.redirect('/vaccines'); return } + + site.status = 'closed' + + res.redirect(`/vaccines?siteTab=deactivated&deactivatedSite=true&siteName=${encodeURIComponent(site.name)}`) + }) + + // View page to reactivate a site + router.get('/vaccines/sites/:siteId/reactivate', (req, res) => { + const currentOrganisationSites = res.locals.currentOrganisation.sites || [] + const site = currentOrganisationSites.find((item) => item.id === req.params.siteId) + if (!site) { res.redirect('/vaccines'); return } + + res.render('vaccines/reactivate-site', { + site + }) + }) + + // Mark site as active + router.post('/vaccines/sites/:siteId/reactivated', (req, res) => { + const currentOrganisationSites = res.locals.currentOrganisation.sites || [] + const site = currentOrganisationSites.find((item) => item.id === req.params.siteId) + if (!site) { res.redirect('/vaccines'); return } + + delete site.status + + res.redirect(`/vaccines?siteTab=active&reactivatedSite=true&siteName=${encodeURIComponent(site.name)}`) + }) + // Adding a batch to an existing vaccine at a site router.post('/vaccines/:id/added', (req, res) => { diff --git a/app/views/vaccines/deactivate-site.html b/app/views/vaccines/deactivate-site.html new file mode 100644 index 00000000..96ab6fb3 --- /dev/null +++ b/app/views/vaccines/deactivate-site.html @@ -0,0 +1,28 @@ +{% extends 'layout.html' %} + +{% set pageName = "Deactivate " + site.name %} + +{% set currentSection = "vaccines" %} + +{% block beforeContent %} + {{ backLink({ href: "/vaccines", text: "Back" }) }} +{% endblock %} + +{% block content %} +
+
+ +

{{ pageName }}

+ +

Are you sure you want to deactivate this site?

+ +
+ {{ button({ + "text": "Confirm deactivate site", + "classes": "nhsuk-button--warning" + }) }} +
+ +
+
+{% endblock %} diff --git a/app/views/vaccines/index.html b/app/views/vaccines/index.html index 86fcbfdb..3a823f8c 100644 --- a/app/views/vaccines/index.html +++ b/app/views/vaccines/index.html @@ -11,12 +11,54 @@ {% endif %} {% endfor %} +{% set filteredSites = [] %} +{% for siteId in sites %} + {% set thisSite = currentOrganisation.sites | findById(siteId) %} + {% if currentSiteTab == "deactivated" %} + {% if thisSite.status == "closed" %} + {% set filteredSites = (filteredSites.push(siteId), filteredSites) %} + {% endif %} + {% else %} + {% if thisSite.status != "closed" %} + {% set filteredSites = (filteredSites.push(siteId), filteredSites) %} + {% endif %} + {% endif %} +{% endfor %} + {% block content %}
{% include "includes/notification.html" %} + {% if deactivatedSite %} + {% set html %} +

+ Site deactivated +

+

{{ (siteName + " has been deactivated.") if siteName else "Site has been deactivated." }}

+ {% endset %} + + {{ notificationBanner({ + html: html, + type: "success" + }) }} + {% endif %} + + {% if reactivatedSite %} + {% set html %} +

+ Site reactivated +

+

{{ (siteName + " has been reactivated.") if siteName else "Site has been reactivated." }}

+ {% endset %} + + {{ notificationBanner({ + html: html, + type: "success" + }) }} + {% endif %} +

Vaccines

@@ -47,14 +89,29 @@

Vaccines

{% from 'select/macro.njk' import select %} - {% if (sites | length) > 4 %} +
+ {{ appSecondaryNavigation({ + visuallyHiddenTitle: "Sites by status", + items: [{ + text: "Active (" + activeSitesCount + ")", + href: "/vaccines?siteTab=active", + current: (currentSiteTab == "active") + }, { + text: "Deactivated (" + deactivatedSitesCount + ")", + href: "/vaccines?siteTab=deactivated", + current: (currentSiteTab == "deactivated") + }] + }) }} +
+ + {% if (filteredSites | length) > 4 %} {% set filterItems = [{ text: "All sites", value: "", selected: true }] %} - {% for site in sites %} + {% for site in filteredSites %} {% set filterItems = (filterItems.push({text: currentOrganisation.sites[site].name, value: site}), filterItems) %} {% endfor %} @@ -74,11 +131,15 @@

Vaccines

- {% for siteId in sites %} + {% if (filteredSites | length) == 0 %} +

No {{ currentSiteTab }} sites found.

+ {% endif %} + + {% for siteId in filteredSites %} {% set site = currentOrganisation.sites | findById(siteId) %} - +
{{ site.name }} {% if site.status == "closed" %} (closed) @@ -152,6 +213,14 @@

Vaccines

{% endfor %}
+ + {% if site.status != "closed" %} +
+

No longer using this site? Deactivate {{ site.name }}

+ {% else %} +
+

Using this site again? Reactivate {{ site.name }}

+ {% endif %} {% endfor %} diff --git a/app/views/vaccines/reactivate-site.html b/app/views/vaccines/reactivate-site.html new file mode 100644 index 00000000..7b9e0607 --- /dev/null +++ b/app/views/vaccines/reactivate-site.html @@ -0,0 +1,27 @@ +{% extends 'layout.html' %} + +{% set pageName = "Reactivate " + site.name %} + +{% set currentSection = "vaccines" %} + +{% block beforeContent %} + {{ backLink({ href: "/vaccines?siteTab=deactivated", text: "Back" }) }} +{% endblock %} + +{% block content %} +
+
+ +

{{ pageName }}

+ +

Are you sure you want to reactivate this site?

+ +
+ {{ button({ + "text": "Confirm reactivate site" + }) }} +
+ +
+
+{% endblock %}