From b2629e96f04c819a7baeda7986716fdefad08bc2 Mon Sep 17 00:00:00 2001 From: "Efrain A. Davila" <105945226+EfrainAD@users.noreply.github.com> Date: Mon, 7 Aug 2023 19:59:19 -0400 Subject: [PATCH 01/41] Feature: The 'Completed' column is now presented as a button if the answer is yes. When clicked, it navigates the user to the survey. 1. I utilized the useGetSurveyVisitsQuery to retrieve all survey data. 2. Within the "Completed" column, I replaced the 'Yes' response with a button that facilitates user navigation to the survey. 3. Next, I regenerated the house data by appending completed: true and survey_id: visit.id. Please note that currently, the built-in method for searching survey visits by quiries is on the to-do list, according to https://docs.google.com/document/d/1QAek7K-pvnCJe4wxm38QdPCbszEE-esw3w-tuhEtMDQ/edit. So, I couldn't directly retrieve it. 4. Should any errors arise from survey visits, a CustomSnackbar is triggered to inform the user. However, the table still loads without interruption. --- .../front/src/pages/Admin/home/HomeTable.js | 80 +++++++++++++++---- 1 file changed, 63 insertions(+), 17 deletions(-) diff --git a/frontend/front/src/pages/Admin/home/HomeTable.js b/frontend/front/src/pages/Admin/home/HomeTable.js index b9735f0d..eee2f062 100644 --- a/frontend/front/src/pages/Admin/home/HomeTable.js +++ b/frontend/front/src/pages/Admin/home/HomeTable.js @@ -8,7 +8,11 @@ import CustomSnackbar from "../../../components/CustomSnackbar"; import { DataGrid } from "@mui/x-data-grid"; import Loader from "../../../components/Loader"; import React from "react"; -import { useGetHomesQuery } from "../../../api/apiSlice"; +import { + useGetHomesQuery, + useGetSurveyVisitsQuery +} from "../../../api/apiSlice"; +import { useNavigate } from "react-router-dom"; // Formats addresses export const getAddress = (params) => { @@ -24,6 +28,7 @@ export const getAddress = (params) => { const HomeTable = () => { const goToBreadcrumb = useGoToBreadcrumb(); + const navigate = useNavigate(); useInitBreadcrumbs([ { url: "/admin/dashboard", description: "dashboard" }, @@ -31,12 +36,17 @@ const HomeTable = () => { ]); const handleHomeLink = (home) => goToBreadcrumb("home", home); + const handleUserLink = (visit) => navigate('/admin/survey/visit/' + visit) const handleAssignmentLink = (assignment) => goToBreadcrumb("assignment", assignment); const columns = [ - { field: "id", headerName: "Id", minWidth: 80 }, + { + field: "id", + headerName: "Id", + minWidth: 80 + }, { field: "address", valueGetter: getAddress, @@ -61,7 +71,15 @@ const HomeTable = () => { { field: "completed", headerName: "Completed", - renderCell: (params) => (params.row.completed === "true" ? "Yes" : "No"), + renderCell: (params) => (params.row.completed === true ? : "No"), minWidth: 100, maxWidth: 150, flex: 0.8, @@ -99,33 +117,61 @@ const HomeTable = () => { ]; const { - data: homesData, - isError: isHomesError, + data: fetchedHomesData, + isError: isFetchedHomesError, isLoading: isHomesDataLoading, } = useGetHomesQuery(); + const { + data: surveyVisitsData, + isError: isSurveyVisitsError, + isLoading: isSurveyVisitsDataLoading, + } = useGetSurveyVisitsQuery() - if (isHomesDataLoading) { + let homesData = []; + + if (surveyVisitsData && fetchedHomesData) { + homesData = Object.values(fetchedHomesData).map(home => { + const visit = surveyVisitsData.find(visit => visit.home_id === home.id); + if (visit) { + return { ...home, completed: true, survey_id: visit.id }; + } + return home; + }); + } + + const isDataReady = !isHomesDataLoading && !isSurveyVisitsDataLoading && fetchedHomesData + + if (!isDataReady) { return ; } return ( - {isHomesError ? ( + {isFetchedHomesError ? ( ) : ( - - )} + <> + {isSurveyVisitsError && ( + )} + + + ) +} ); }; From 626f895f7378c4268d497fe7448f82d7d37ad35b Mon Sep 17 00:00:00 2001 From: "Efrain A. Davila" <105945226+EfrainAD@users.noreply.github.com> Date: Sat, 12 Aug 2023 21:58:12 -0400 Subject: [PATCH 02/41] formatted the file with prettier --- .../front/src/pages/Admin/home/HomeTable.js | 70 ++++++++++--------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/frontend/front/src/pages/Admin/home/HomeTable.js b/frontend/front/src/pages/Admin/home/HomeTable.js index eee2f062..f0fbbd04 100644 --- a/frontend/front/src/pages/Admin/home/HomeTable.js +++ b/frontend/front/src/pages/Admin/home/HomeTable.js @@ -8,9 +8,9 @@ import CustomSnackbar from "../../../components/CustomSnackbar"; import { DataGrid } from "@mui/x-data-grid"; import Loader from "../../../components/Loader"; import React from "react"; -import { - useGetHomesQuery, - useGetSurveyVisitsQuery +import { + useGetHomesQuery, + useGetSurveyVisitsQuery, } from "../../../api/apiSlice"; import { useNavigate } from "react-router-dom"; @@ -36,16 +36,16 @@ const HomeTable = () => { ]); const handleHomeLink = (home) => goToBreadcrumb("home", home); - const handleUserLink = (visit) => navigate('/admin/survey/visit/' + visit) + const handleUserLink = (visit) => navigate("/admin/survey/visit/" + visit); const handleAssignmentLink = (assignment) => goToBreadcrumb("assignment", assignment); const columns = [ { - field: "id", - headerName: "Id", - minWidth: 80 + field: "id", + headerName: "Id", + minWidth: 80, }, { field: "address", @@ -71,15 +71,20 @@ const HomeTable = () => { { field: "completed", headerName: "Completed", - renderCell: (params) => (params.row.completed === true ? : "No"), + renderCell: (params) => + params.row.completed === true ? ( + + ) : ( + "No" + ), minWidth: 100, maxWidth: 150, flex: 0.8, @@ -125,22 +130,23 @@ const HomeTable = () => { data: surveyVisitsData, isError: isSurveyVisitsError, isLoading: isSurveyVisitsDataLoading, - } = useGetSurveyVisitsQuery() + } = useGetSurveyVisitsQuery(); let homesData = []; if (surveyVisitsData && fetchedHomesData) { - homesData = Object.values(fetchedHomesData).map(home => { - const visit = surveyVisitsData.find(visit => visit.home_id === home.id); + homesData = Object.values(fetchedHomesData).map((home) => { + const visit = surveyVisitsData.find((visit) => visit.home_id === home.id); if (visit) { return { ...home, completed: true, survey_id: visit.id }; } return home; }); } - - const isDataReady = !isHomesDataLoading && !isSurveyVisitsDataLoading && fetchedHomesData - + + const isDataReady = + !isHomesDataLoading && !isSurveyVisitsDataLoading && fetchedHomesData; + if (!isDataReady) { return ; } @@ -160,18 +166,18 @@ const HomeTable = () => { open={isSurveyVisitsError} message="Error fetching Survey Visits data." severity="error" - />)} - + )} + - ) -} + )} ); }; From 3fa6f7c88e573d822182abfe1dca158be5512e76 Mon Sep 17 00:00:00 2001 From: "Efrain A. Davila" <105945226+EfrainAD@users.noreply.github.com> Date: Sat, 12 Aug 2023 22:02:08 -0400 Subject: [PATCH 03/41] did what eslint told me so it could pass --- frontend/front/package.json | 1 + frontend/front/yarn.lock | 48 ++++++++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/frontend/front/package.json b/frontend/front/package.json index ef9f67ac..f42afb39 100644 --- a/frontend/front/package.json +++ b/frontend/front/package.json @@ -59,6 +59,7 @@ ] }, "devDependencies": { + "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "eslint": "^8.44.0", "npm-run-all": "^4.1.5", "prettier": "^2.8.8" diff --git a/frontend/front/yarn.lock b/frontend/front/yarn.lock index 00852e0b..e9e79865 100644 --- a/frontend/front/yarn.lock +++ b/frontend/front/yarn.lock @@ -86,7 +86,7 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" -"@babel/helper-annotate-as-pure@^7.22.5": +"@babel/helper-annotate-as-pure@^7.18.6", "@babel/helper-annotate-as-pure@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== @@ -126,6 +126,21 @@ "@babel/helper-split-export-declaration" "^7.22.5" semver "^6.3.0" +"@babel/helper-create-class-features-plugin@^7.21.0": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.10.tgz#dd2612d59eac45588021ac3d6fa976d08f4e95a3" + integrity sha512-5IBb77txKYQPpOEdUdIhBx8VrZyDCQ+H82H0+5dX1TmuscP5vJKEE3cKurjtIw/vFwzbVH48VweE78kVDBrqjA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-member-expression-to-functions" "^7.22.5" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + semver "^6.3.1" + "@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.5.tgz#bb2bf0debfe39b831986a4efbf4066586819c6e4" @@ -229,6 +244,15 @@ "@babel/traverse" "^7.22.5" "@babel/types" "^7.22.5" +"@babel/helper-replace-supers@^7.22.9": + version "7.22.9" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz#cbdc27d6d8d18cd22c81ae4293765a5d9afd0779" + integrity sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg== + dependencies: + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-member-expression-to-functions" "^7.22.5" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-simple-access@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" @@ -250,6 +274,13 @@ dependencies: "@babel/types" "^7.22.5" +"@babel/helper-split-export-declaration@^7.22.6": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" + integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-string-parser@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" @@ -371,6 +402,16 @@ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== +"@babel/plugin-proposal-private-property-in-object@^7.21.11": + version "7.21.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz#69d597086b6760c4126525cfa154f34631ff272c" + integrity sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-create-class-features-plugin" "^7.21.0" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e" @@ -8626,6 +8667,11 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + semver@^7.3.2, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8: version "7.5.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" From 4c64c45d94893629398f1744690597dbdd7ab360 Mon Sep 17 00:00:00 2001 From: Mike Lynch Date: Tue, 8 Aug 2023 20:50:00 -0400 Subject: [PATCH 04/41] Remove completed attribute from survey_response and calculate instead (#405) * Remove completed attribute from survey_responses Co-authored-by: Anna Westland-Tegart Co-authored-by: Linden Huhmann * Add visited? attribute to home Add a visited attribute to the homes model, which indicates whether it has any survey_visits. Eager load the survey_visits for a home inside the homes and assignments controllers to avoid N+1 queries issue. * Fix bug and rubocop issue * Add completed attribute to homes model * Update order of home attributes on assignment view Make the attribute order consistent when seeing home details from homes controller and from assignments controller. * Fix bug when filtering assignments by surveyor * Return viewed/completed attributes without question marks --------- Co-authored-by: Anna Westland-Tegart Co-authored-by: Linden Huhmann --- backend/app/controllers/assignments_controller.rb | 8 +++++--- backend/app/controllers/homes_controller.rb | 4 ++-- backend/app/models/assignment.rb | 2 ++ backend/app/models/home.rb | 10 ++++++++++ .../app/views/assignments/_assignment.json.jbuilder | 4 ++-- ...0621000051_remove_completed_from_survey_response.rb | 7 +++++++ backend/db/schema.rb | 1 - 7 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 backend/db/migrate/20230621000051_remove_completed_from_survey_response.rb diff --git a/backend/app/controllers/assignments_controller.rb b/backend/app/controllers/assignments_controller.rb index c29731de..7a382974 100644 --- a/backend/app/controllers/assignments_controller.rb +++ b/backend/app/controllers/assignments_controller.rb @@ -5,10 +5,12 @@ class AssignmentsController < ApplicationController # GET /assignments or /assignments.json def index + coll = Assignment.includes(homes: { survey_visits: :survey_response }) + @assignments = if search_params[:surveyor_id] - Assignment.joins(:surveyors).where({ surveyors: { id: search_params[:surveyor_id] } }) + coll.filter_by_surveyor [search_params[:surveyor_id]] else - Assignment.all + coll.all end end @@ -60,7 +62,7 @@ def destroy # Use callbacks to share common setup or constraints between actions. def set_assignment - @assignment = Assignment.find(params[:id]) + @assignment = Assignment.includes(homes: { survey_visits: :survey_response }).find(params[:id]) end # Only allow a list of trusted parameters through. diff --git a/backend/app/controllers/homes_controller.rb b/backend/app/controllers/homes_controller.rb index ae05b875..9163836a 100644 --- a/backend/app/controllers/homes_controller.rb +++ b/backend/app/controllers/homes_controller.rb @@ -5,7 +5,7 @@ class HomesController < ApplicationController # GET /homes or /homes.json def index - @homes = Home.where(search_params) + @homes = Home.includes(survey_visits: :survey_response).where(search_params) end # GET /homes/1 or /homes/1.json @@ -56,7 +56,7 @@ def destroy # Use callbacks to share common setup or constraints between actions. def set_home - @home = Home.find(params[:id]) + @home = Home.includes(survey_visits: :survey_response).find(params[:id]) end # Only allow a list of trusted parameters through. diff --git a/backend/app/models/assignment.rb b/backend/app/models/assignment.rb index 77c175d3..57454d80 100644 --- a/backend/app/models/assignment.rb +++ b/backend/app/models/assignment.rb @@ -4,4 +4,6 @@ class Assignment < ApplicationRecord has_and_belongs_to_many :surveyors has_many :homes, dependent: nil validates :region_code, numericality: true + + scope :filter_by_surveyor, ->(surveyor_ids) { joins(:surveyors).where(surveyors: { id: surveyor_ids }) } end diff --git a/backend/app/models/home.rb b/backend/app/models/home.rb index 3aa965e9..7912afbc 100644 --- a/backend/app/models/home.rb +++ b/backend/app/models/home.rb @@ -11,4 +11,14 @@ class Home < ApplicationRecord # Ensure visit_order has a value iff assignment_id does validates :visit_order, presence: true, if: :assignment_id validates :assignment_id, presence: true, if: :visit_order + + def visited? + !survey_visits.empty? + end + + def completed? + # We consider a home completed if any of its survey_visits + # have an associated survey_response + survey_visits.any? { |sv| !sv.survey_response.nil? } + end end diff --git a/backend/app/views/assignments/_assignment.json.jbuilder b/backend/app/views/assignments/_assignment.json.jbuilder index e9bcbe49..0064b165 100644 --- a/backend/app/views/assignments/_assignment.json.jbuilder +++ b/backend/app/views/assignments/_assignment.json.jbuilder @@ -9,6 +9,6 @@ end json.homes do json.array!(assignment.homes.sort_by do |h| h[:visit_order] - end, :id, :visit_order, :street_number, :street_name, :unit_number, :city, :state, :zip_code, - :building_type) + end, :id, :street_number, :street_name, :unit_number, :city, :state, :zip_code, + :building_type, :visit_order, :visited?, :completed?) end diff --git a/backend/db/migrate/20230621000051_remove_completed_from_survey_response.rb b/backend/db/migrate/20230621000051_remove_completed_from_survey_response.rb new file mode 100644 index 00000000..d0ab8c12 --- /dev/null +++ b/backend/db/migrate/20230621000051_remove_completed_from_survey_response.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class RemoveCompletedFromSurveyResponse < ActiveRecord::Migration[7.0] + def change + remove_column :survey_responses, :completed, :boolean + end +end diff --git a/backend/db/schema.rb b/backend/db/schema.rb index 8ed535db..2432eb99 100644 --- a/backend/db/schema.rb +++ b/backend/db/schema.rb @@ -96,7 +96,6 @@ t.datetime "updated_at", null: false t.string "ip" t.float "recaptcha_score" - t.boolean "completed" t.index ["survey_id"], name: "index_survey_responses_on_survey_id" t.index ["survey_visit_id"], name: "index_survey_responses_on_survey_visit_id" end From 16402ed30097025265dc8be8e965f9de2a1c1e64 Mon Sep 17 00:00:00 2001 From: Matt DelSordo Date: Tue, 8 Aug 2023 20:50:46 -0400 Subject: [PATCH 05/41] commit format on save setting --- .gitignore | 1 - .vscode/settings.json | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index ed651eff..b629fa6d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ # ignore IDE settings .idea -.vscode frontend/front/.env node_modules yarn.lock \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..9bf4d12b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true +} From 6b19fb4648b677ff2b76fa47031d394c2855d26c Mon Sep 17 00:00:00 2001 From: Matt DelSordo Date: Sun, 6 Aug 2023 14:31:25 -0400 Subject: [PATCH 06/41] routing fixes --- .github/workflows/test.yml | 4 +- backend/Dockerfile | 6 ++- .../assignments/_assignment.json.jbuilder | 2 +- backend/docker-compose.yml | 5 ++- frontend/front/src/components/AddressUtils.js | 45 ++++++++++++++----- .../Surveyor/dashboard/AssignmentUnit.js | 6 ++- .../front/src/pages/Surveyor/map/mapUtils.js | 2 +- 7 files changed, 50 insertions(+), 20 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6f22c799..9369f65c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -78,7 +78,7 @@ jobs: runs-on: ubuntu-latest defaults: run: - working-directory: backend + working-directory: . needs: [test-backend] steps: - name: Check out code @@ -106,4 +106,4 @@ jobs: ECR_REPOSITORY: urban-league-heat-pump-accelerator IMAGE_TAG: ${{ github.sha }} run: | - docker buildx build --platform linux/arm64 -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . --push + docker buildx build --platform linux/arm64 -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG -f ./backend/Dockerfile . --push diff --git a/backend/Dockerfile b/backend/Dockerfile index 088f73ee..4dadf9e9 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -2,12 +2,14 @@ FROM ruby:3.1.3-alpine RUN apk update && apk upgrade && apk add build-base libpq-dev postgresql-client gcompat tzdata WORKDIR /usr/src/app -COPY Gemfile Gemfile.lock ./ +# path context is the repo root +COPY backend/Gemfile backend/Gemfile.lock ./ # add x86_64 for support on ARM platform - nokogiri expects x86 for distribution RUN bundle lock --add-platform x86_64-linux RUN bundle install -COPY . . +COPY ./backend . +COPY ./data-analysis/* /usr/src/data-analysis/ EXPOSE 3000 RUN chmod +x start.sh diff --git a/backend/app/views/assignments/_assignment.json.jbuilder b/backend/app/views/assignments/_assignment.json.jbuilder index 0064b165..8ecc2a6b 100644 --- a/backend/app/views/assignments/_assignment.json.jbuilder +++ b/backend/app/views/assignments/_assignment.json.jbuilder @@ -10,5 +10,5 @@ json.homes do json.array!(assignment.homes.sort_by do |h| h[:visit_order] end, :id, :street_number, :street_name, :unit_number, :city, :state, :zip_code, - :building_type, :visit_order, :visited?, :completed?) + :building_type, :visit_order, :visited?, :completed?, :latitude, :longitude) end diff --git a/backend/docker-compose.yml b/backend/docker-compose.yml index 54482375..5201d33a 100644 --- a/backend/docker-compose.yml +++ b/backend/docker-compose.yml @@ -3,7 +3,10 @@ services: environment: DATABASE_URL: 'postgres://postgres:password123@db' JWT_SECRET_KEY: '${JWT_SECRET_KEY}' - build: . + build: + dockerfile: ./backend/Dockerfile + # set context to repo root so that the data can be passed in + context: ../ ports: - '3000:3000' links: diff --git a/frontend/front/src/components/AddressUtils.js b/frontend/front/src/components/AddressUtils.js index 9387e7d1..c4430a03 100644 --- a/frontend/front/src/components/AddressUtils.js +++ b/frontend/front/src/components/AddressUtils.js @@ -1,20 +1,41 @@ -import React from "react"; +import React, { useMemo } from "react"; import { Card, CardContent } from "@mui/material"; /** * Component for displaying a home address */ -export const AddressComponent = ({ home }) => ( - - -
-

{"Address:"}

-
{`${home?.street_number} ${home?.street_name} #${home?.unit_number}`}
-
{`${home?.city}, ${home?.state} ${home?.zip_code}`}
-
-
-
-); +export const AddressComponent = ({ home }) => { + const line1 = useMemo(() => { + if (home) { + let line = `${home.street_number} ${home.street_name}`; + if (home.unit_number) { + line += ` #${home.unit_number}`; + } + return line; + } + + return ""; + }, [home]); + + const line2 = useMemo(() => { + if (home) { + return `${home.city}, ${home.state} ${home.zip_code}`; + } + return ""; + }, [home]); + + return ( + + +
+

{"Address:"}

+
{line1}
+
{line2}
+
+
+
+ ); +}; export const houseToString = (home) => { if (!home) { diff --git a/frontend/front/src/pages/Surveyor/dashboard/AssignmentUnit.js b/frontend/front/src/pages/Surveyor/dashboard/AssignmentUnit.js index 6ed3cd4c..6f8c9e93 100644 --- a/frontend/front/src/pages/Surveyor/dashboard/AssignmentUnit.js +++ b/frontend/front/src/pages/Surveyor/dashboard/AssignmentUnit.js @@ -59,7 +59,11 @@ const AssignmentUnit = ({ data }) => { - - - - - - - - ); -}; - -export default Dashboard; diff --git a/frontend/front/src/pages/Admin/home/CreateNewHome.js b/frontend/front/src/pages/Admin/home/CreateNewHome.js index 056cfec2..546c299c 100644 --- a/frontend/front/src/pages/Admin/home/CreateNewHome.js +++ b/frontend/front/src/pages/Admin/home/CreateNewHome.js @@ -4,6 +4,8 @@ import { Controller, useForm } from "react-hook-form"; import React from "react"; import { useNavigate } from "react-router-dom"; +import { withAdminPrefix, ADMIN_HOME } from "../../../routing/routes"; + const CreateNewHome = () => { const navigate = useNavigate(); const { handleSubmit, control } = useForm({ @@ -18,7 +20,7 @@ const CreateNewHome = () => { const onSubmit = (data) => console.log(data); const handleCancel = () => { - navigate("/admin/home"); + navigate(withAdminPrefix(ADMIN_HOME)); }; return ( diff --git a/frontend/front/src/pages/Admin/home/HomeProfile.js b/frontend/front/src/pages/Admin/home/HomeProfile.js index a4ca9d55..5d33f7ff 100644 --- a/frontend/front/src/pages/Admin/home/HomeProfile.js +++ b/frontend/front/src/pages/Admin/home/HomeProfile.js @@ -5,6 +5,7 @@ import { useGetHomeQuery } from "../../../api/apiSlice"; import Loader from "../../../../src/components/Loader.js"; import CustomSnackbar from "../../../components/CustomSnackbar"; import { AdminBackButton } from "../../Surveyor/Components/AdminBackButton"; +import { ADMIN_HOME, withAdminPrefix } from "../../../routing/routes"; const HomeProfile = () => { const { hid } = useParams(); @@ -64,7 +65,7 @@ const HomeProfile = () => { alignItems="center" flexDirection="column" > - + {isHomeDataLoading ? ( ) : isHomeDataError ? ( diff --git a/frontend/front/src/pages/Admin/home/HomeTable.js b/frontend/front/src/pages/Admin/home/HomeTable.js index e0e2b631..6f3a426c 100644 --- a/frontend/front/src/pages/Admin/home/HomeTable.js +++ b/frontend/front/src/pages/Admin/home/HomeTable.js @@ -13,6 +13,7 @@ import { useGetSurveyVisitsQuery, } from "../../../api/apiSlice"; import { useNavigate } from "react-router-dom"; +import { ADMIN_HOME, withAdminPrefix } from "../../../routing/routes"; // Formats addresses export const getAddress = (params) => { @@ -30,10 +31,10 @@ const HomeTable = () => { const goToBreadcrumb = useGoToBreadcrumb(); const navigate = useNavigate(); - useInitBreadcrumbs([ - { url: "/admin/dashboard", description: "dashboard" }, - { url: "/admin/home", description: "homes" }, - ]); + useInitBreadcrumbs( + [{ url: withAdminPrefix(ADMIN_HOME), description: "homes" }], + true + ); const handleHomeLink = (home) => goToBreadcrumb("home", home); const handleUserLink = (visit) => navigate("/admin/survey/visit/" + visit); diff --git a/frontend/front/src/pages/Admin/home/SurveyVisitProfile.js b/frontend/front/src/pages/Admin/home/SurveyVisitProfile.js index 9e101074..d3d568c5 100644 --- a/frontend/front/src/pages/Admin/home/SurveyVisitProfile.js +++ b/frontend/front/src/pages/Admin/home/SurveyVisitProfile.js @@ -13,6 +13,7 @@ import Loader from "../../../components/Loader"; import { SurveyError } from "../survey/SurveyError"; import { formatISODate } from "../../../components/DateUtils"; import { houseToString } from "../../../components/AddressUtils"; +import { withAdminPrefix, ADMIN_SURVEY } from "../../../routing/routes"; const SurveyProfile = () => { const navigate = useNavigate(); @@ -60,7 +61,7 @@ const SurveyProfile = () => { const onDelete = useCallback(() => { deleteSurveyVisit(surveyVisitId); - navigate("/admin/survey"); + navigate(withAdminPrefix(ADMIN_SURVEY)); }, [deleteSurveyVisit, surveyVisitId, navigate]); return ( diff --git a/frontend/front/src/pages/Admin/nav/Nav.js b/frontend/front/src/pages/Admin/nav/Nav.js index 9817bef7..decde38f 100644 --- a/frontend/front/src/pages/Admin/nav/Nav.js +++ b/frontend/front/src/pages/Admin/nav/Nav.js @@ -12,9 +12,6 @@ const Nav = () => { - diff --git a/frontend/front/src/pages/Admin/survey/SurveyProfile.js b/frontend/front/src/pages/Admin/survey/SurveyProfile.js index 17a4e574..309c3b26 100644 --- a/frontend/front/src/pages/Admin/survey/SurveyProfile.js +++ b/frontend/front/src/pages/Admin/survey/SurveyProfile.js @@ -7,15 +7,19 @@ import { SurveyEditorForm } from "./SurveyEditorForm"; import { useGetSurveyStructureQuery } from "../../../api/apiSlice"; import { useInitBreadcrumbs } from "../../../hooks/breadcrumbHooks"; import { useParams } from "react-router-dom"; +import { + adminSurveyEdit, + ADMIN_SURVEY, + withAdminPrefix, +} from "../../../routing/routes"; const SurveyProfile = () => { const { uid: surveyVisitId } = useParams(); useInitBreadcrumbs([ - { url: "/admin/dashboard", description: "dashboard" }, - { url: "/admin/survey", description: "surveys" }, + { url: withAdminPrefix(ADMIN_SURVEY), description: "surveys" }, { - url: `/admin/survey/edit/${surveyVisitId}`, + url: withAdminPrefix(adminSurveyEdit(surveyVisitId)), description: `survey ${surveyVisitId}`, }, ]); diff --git a/frontend/front/src/pages/Admin/survey/SurveyTable.js b/frontend/front/src/pages/Admin/survey/SurveyTable.js index 902c6ae0..bd825245 100644 --- a/frontend/front/src/pages/Admin/survey/SurveyTable.js +++ b/frontend/front/src/pages/Admin/survey/SurveyTable.js @@ -8,6 +8,7 @@ import Loader from "../../../components/Loader"; import { SurveyError } from "./SurveyError"; import { formatISODate } from "../../../components/DateUtils"; import { useGetSurveysQuery } from "../../../api/apiSlice"; +import { ADMIN_SURVEY, withAdminPrefix } from "../../../routing/routes"; const COLUMNS = [ { field: "id", headerName: "ID", flex: 1 }, @@ -19,10 +20,10 @@ const COLUMNS = [ const SurveyTable = () => { const goToBreadcrumb = useGoToBreadcrumb(); - useInitBreadcrumbs([ - { url: "/admin/dashboard", description: "dashboard" }, - { url: "/admin/survey", description: "surveys" }, - ]); + useInitBreadcrumbs( + [{ url: withAdminPrefix(ADMIN_SURVEY), description: "surveys" }], + true + ); const { data: surveyData, diff --git a/frontend/front/src/pages/Admin/user/CreateNewUser.js b/frontend/front/src/pages/Admin/user/CreateNewUser.js index 4db2f3b1..08f8e264 100644 --- a/frontend/front/src/pages/Admin/user/CreateNewUser.js +++ b/frontend/front/src/pages/Admin/user/CreateNewUser.js @@ -24,6 +24,7 @@ import { HeatPumpTextField } from "../../../components/SurveyComponent/HeatPumpT import Loader from "../../../components/Loader"; import { useForm } from "react-hook-form"; import { useNavigate } from "react-router-dom"; +import { withAdminPrefix, ADMIN_USER } from "../../../routing/routes"; const ACTION_BACK = "BACK"; const ACTION_NEW = "NEW"; @@ -53,7 +54,7 @@ const CreateNewUser = () => { const [createSurveyor] = useCreateSurveyorMutation(); const handleCancel = useCallback(() => { - navigate("/admin/user"); + navigate(withAdminPrefix(ADMIN_USER)); }, [navigate]); const onSubmit = useCallback( diff --git a/frontend/front/src/pages/Admin/user/UserProfile.js b/frontend/front/src/pages/Admin/user/UserProfile.js index 5f188677..89bb4817 100644 --- a/frontend/front/src/pages/Admin/user/UserProfile.js +++ b/frontend/front/src/pages/Admin/user/UserProfile.js @@ -8,6 +8,7 @@ import CustomSnackbar from "../../../components/CustomSnackbar"; import Loader from "../../../components/Loader"; import { useGetSurveyorQuery } from "../../../api/apiSlice"; import { useParams } from "react-router-dom"; +import { ADMIN_USER, withAdminPrefix } from "../../../routing/routes"; const UserProfile = () => { const { uid } = useParams(); @@ -92,7 +93,7 @@ const UserProfile = () => { alignItems="center" flexDirection="column" > - + {isSurveyorDataLoading ? ( ) : isSurveyorError ? ( diff --git a/frontend/front/src/pages/Admin/user/UserTable.js b/frontend/front/src/pages/Admin/user/UserTable.js index 8083fa68..43373173 100644 --- a/frontend/front/src/pages/Admin/user/UserTable.js +++ b/frontend/front/src/pages/Admin/user/UserTable.js @@ -10,10 +10,12 @@ import TableContainer from "@mui/material/TableContainer"; import TableHead from "@mui/material/TableHead"; import TablePagination from "@mui/material/TablePagination"; import TableRow from "@mui/material/TableRow"; -import { setBreadcrumbs } from "../../../features/breadcrumb/breadcrumbSlice"; -import { useDispatch } from "react-redux"; import { useGetSurveyorsQuery } from "../../../api/apiSlice"; -import { useGoToBreadcrumb } from "../../../hooks/breadcrumbHooks"; +import { + useGoToBreadcrumb, + useInitBreadcrumbs, +} from "../../../hooks/breadcrumbHooks"; +import { ADMIN_USER, withAdminPrefix } from "../../../routing/routes"; const columns = [ { id: "id", label: "UserID", minWidth: 50 }, @@ -26,14 +28,11 @@ const columns = [ ]; const UserTable = () => { - const dispatch = useDispatch(); const goToBreadcrumb = useGoToBreadcrumb(); - dispatch( - setBreadcrumbs([ - { url: "/admin/dashboard", description: "dashboard" }, - { url: "/admin/user", description: "users" }, - ]) + useInitBreadcrumbs( + [{ url: withAdminPrefix(ADMIN_USER), description: "users" }], + true ); const { diff --git a/frontend/front/src/pages/Surveyor/nav/Nav.js b/frontend/front/src/pages/Surveyor/nav/Nav.js index 2aaeb9f7..a375bde3 100644 --- a/frontend/front/src/pages/Surveyor/nav/Nav.js +++ b/frontend/front/src/pages/Surveyor/nav/Nav.js @@ -10,6 +10,7 @@ import React from "react"; import { selectCurrentUserEmail } from "../../../features/login/loginSlice"; import { useLogoutUserMutation } from "../../../api/apiSlice"; import { useSelector } from "react-redux"; +import { ADMIN_ROUTE } from "../../../routing/routes"; const Nav = () => { const [logout] = useLogoutUserMutation(); @@ -32,7 +33,7 @@ const Nav = () => { {userIsAdmin && ( - - + {renderMedia()} ); } diff --git a/frontend/front/src/pages/Public/Pages/AboutHeatPump/AboutHeatPump.js b/frontend/front/src/pages/Public/Pages/AboutHeatPump/AboutHeatPump.js index 9231afc3..2c793ae5 100644 --- a/frontend/front/src/pages/Public/Pages/AboutHeatPump/AboutHeatPump.js +++ b/frontend/front/src/pages/Public/Pages/AboutHeatPump/AboutHeatPump.js @@ -6,6 +6,7 @@ import Heading1 from "../../Components/Typography/Heading1"; import Heading1BlueBgGround from "../../Components/Typography/Heading1BlueBgGround"; import Heading4 from "../../Components/Typography/Heading4"; import AboutHeatPumpCards from "./AboutHeatPumpsCards"; +import CardsSection from "../../Components/CardsSection"; const cardContent = [ { @@ -51,7 +52,7 @@ function AboutHeatPump() { > - + {/* {isSmallerThanMd ? ( )} - - + */} + {/* {cardContent.map((card, index) => { return ( ); })} - - + */} + + + {cardContent.map((card, index) => { + return ( + + ); + })} + + diff --git a/frontend/front/src/pages/Public/Pages/BenefitsHeatPumps.js b/frontend/front/src/pages/Public/Pages/BenefitsHeatPumps.js index a02eba75..8fafdc9e 100644 --- a/frontend/front/src/pages/Public/Pages/BenefitsHeatPumps.js +++ b/frontend/front/src/pages/Public/Pages/BenefitsHeatPumps.js @@ -24,7 +24,7 @@ const cardBenefits = [ { icon: moneyIcon, title: "Saving Money", - body: "Air source heat pumps (ASHPs) can reduce electricity usage for heating by up to 50% compared to electrical furnaces and baseboard heaters. (Environmental Protection Agency - link). For cooling, ASHPs are roughly equivalent to “central air conditioning” and far more efficient than window AC units. Together, this can translate into homeowner savings of 20%-40% off of their annual heating and cooling bills. To compare your system and to see how much you could save, ", + body: "Air source heat pumps (ASHPs) can reduce electricity usage for heating by up to 50% compared to electrical furnaces and baseboard heaters. For cooling, ASHPs are roughly equivalent to “central air conditioning” and far more efficient than window AC units. Together, this can translate into homeowner savings of 20%-40% off of their annual heating and cooling bills. To compare your system and to see how much you could save, ", link: "https://www.masssave.com/residential/heating-comparison-calculator", }, { @@ -65,7 +65,7 @@ const BenefitsHeatPumps = () => { - + {/* {isSmallerThanSmm ? ( { )} - + */} {cardBenefits.map((card) => ( diff --git a/frontend/front/src/pages/Public/Pages/GetInvolved.js b/frontend/front/src/pages/Public/Pages/GetInvolved.js index ef2bbbd3..496afeaf 100644 --- a/frontend/front/src/pages/Public/Pages/GetInvolved.js +++ b/frontend/front/src/pages/Public/Pages/GetInvolved.js @@ -56,12 +56,12 @@ function GetInvolved() { > - + {/* - + */} ), }, @@ -53,7 +53,7 @@ function CarrouselHero(props) { interval="8000" indicators={false} cycleNavigation={false} - // autoPlay={false} + autoPlay={false} styles={{ height: { heroHeight }, minHeight: "100vh", From 50d8b9e7234d2a16b2312d0c850b76ac13fe606e Mon Sep 17 00:00:00 2001 From: thiagobadini Date: Tue, 1 Aug 2023 21:14:09 -0400 Subject: [PATCH 13/41] added text --- frontend/front/src/pages/Public/Pages/BenefitsHeatPumps.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/front/src/pages/Public/Pages/BenefitsHeatPumps.js b/frontend/front/src/pages/Public/Pages/BenefitsHeatPumps.js index 8fafdc9e..203adcb5 100644 --- a/frontend/front/src/pages/Public/Pages/BenefitsHeatPumps.js +++ b/frontend/front/src/pages/Public/Pages/BenefitsHeatPumps.js @@ -24,7 +24,7 @@ const cardBenefits = [ { icon: moneyIcon, title: "Saving Money", - body: "Air source heat pumps (ASHPs) can reduce electricity usage for heating by up to 50% compared to electrical furnaces and baseboard heaters. For cooling, ASHPs are roughly equivalent to “central air conditioning” and far more efficient than window AC units. Together, this can translate into homeowner savings of 20%-40% off of their annual heating and cooling bills. To compare your system and to see how much you could save, ", + body: "Air source heat pumps (ASHPs) can reduce electricity usage for heating by up to 50% compared to electrical furnaces and baseboard heaters (source). For cooling, ASHPs are roughly equivalent to “central air conditioning” and far more efficient than window AC units. Together, this can translate into homeowner savings of 20%-40% off of their annual heating and cooling bills. To compare your system and to see how much you could save, ", link: "https://www.masssave.com/residential/heating-comparison-calculator", }, { From 471bee96aff95bc436ea9cc6d026d1ef5228d043 Mon Sep 17 00:00:00 2001 From: thiagobadini Date: Tue, 15 Aug 2023 18:29:14 -0400 Subject: [PATCH 14/41] Added the links to the logos - about us --- .../src/pages/Public/Pages/AboutUs/AboutUs.js | 20 ++++++++--------- .../pages/Public/Pages/AboutUs/PartnerTile.js | 22 +++++++++---------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/frontend/front/src/pages/Public/Pages/AboutUs/AboutUs.js b/frontend/front/src/pages/Public/Pages/AboutUs/AboutUs.js index ce20ff3c..930c23da 100644 --- a/frontend/front/src/pages/Public/Pages/AboutUs/AboutUs.js +++ b/frontend/front/src/pages/Public/Pages/AboutUs/AboutUs.js @@ -48,17 +48,15 @@ function AboutUs() { alignContent={"flex-start"} flexDirection={{ xs: "column", md: "row" }} > - - + + + The Urban League of Eastern Massachusetts (ULEM) is the diff --git a/frontend/front/src/pages/Public/Pages/AboutUs/PartnerTile.js b/frontend/front/src/pages/Public/Pages/AboutUs/PartnerTile.js index ae6e13a7..9c4e4e66 100644 --- a/frontend/front/src/pages/Public/Pages/AboutUs/PartnerTile.js +++ b/frontend/front/src/pages/Public/Pages/AboutUs/PartnerTile.js @@ -8,17 +8,17 @@ const PartnerTile = ({ partnerName, paragraphText, image, website }) => { direction={{ xs: "column", md: "row" }} alignItems={{ xs: "center", md: "flex-start" }} > - - + + + {partnerName} {paragraphText} From a05fc029fe1698b7da09c451fc2349ac31008801 Mon Sep 17 00:00:00 2001 From: thiagobadini Date: Tue, 15 Aug 2023 18:34:05 -0400 Subject: [PATCH 15/41] Added links to the partners names - about us --- .../src/pages/Public/Pages/AboutUs/AboutUs.js | 24 +++++++++++++------ .../pages/Public/Pages/AboutUs/PartnerTile.js | 13 +++++++++- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/frontend/front/src/pages/Public/Pages/AboutUs/AboutUs.js b/frontend/front/src/pages/Public/Pages/AboutUs/AboutUs.js index 930c23da..f831ad30 100644 --- a/frontend/front/src/pages/Public/Pages/AboutUs/AboutUs.js +++ b/frontend/front/src/pages/Public/Pages/AboutUs/AboutUs.js @@ -59,13 +59,23 @@ function AboutUs() { - The Urban League of Eastern Massachusetts (ULEM) is the - sponsor of the BHPA effort. Since 1919, ULEM has delivered - workforce and economic development services and programs to - increase self-reliance of residents of the Boston community - and surrounding metropolitan areas. ULEM is a 501c3 nonprofit - organization and one of the oldest affiliates within the - National Urban League movement.{" "} + + The Urban League of Eastern Massachusetts (ULEM) + {" "} + is the sponsor of the BHPA effort. Since 1919, ULEM has + delivered workforce and economic development services and + programs to increase self-reliance of residents of the Boston + community and surrounding metropolitan areas. ULEM is a 501c3 + nonprofit organization and one of the oldest affiliates within + the National Urban League movement.{" "} diff --git a/frontend/front/src/pages/Public/Pages/AboutUs/PartnerTile.js b/frontend/front/src/pages/Public/Pages/AboutUs/PartnerTile.js index 9c4e4e66..4dbb4505 100644 --- a/frontend/front/src/pages/Public/Pages/AboutUs/PartnerTile.js +++ b/frontend/front/src/pages/Public/Pages/AboutUs/PartnerTile.js @@ -21,7 +21,18 @@ const PartnerTile = ({ partnerName, paragraphText, image, website }) => { - {partnerName} {paragraphText} + + {partnerName} + {" "} + {paragraphText} From 1c8ae99bc04e25094159dd8f9051b4478564cdf0 Mon Sep 17 00:00:00 2001 From: thiagobadini Date: Tue, 15 Aug 2023 18:47:13 -0400 Subject: [PATCH 16/41] Added source link - Benefits of Heat Pump --- .../pages/Public/Pages/BenefitsHeatPumps.js | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/frontend/front/src/pages/Public/Pages/BenefitsHeatPumps.js b/frontend/front/src/pages/Public/Pages/BenefitsHeatPumps.js index 203adcb5..7ca1df4f 100644 --- a/frontend/front/src/pages/Public/Pages/BenefitsHeatPumps.js +++ b/frontend/front/src/pages/Public/Pages/BenefitsHeatPumps.js @@ -10,7 +10,6 @@ import { Icon, } from "@mui/material"; import Heading1BlueBgGround from "../Components/Typography/Heading1BlueBgGround"; -import Heading1 from "../Components/Typography/Heading1"; import Heading3 from "../Components/Typography/Heading3"; import Heading4 from "../Components/Typography/Heading4"; import moneyIcon from "../../../assets/images/Icons/money.png"; @@ -24,25 +23,32 @@ const cardBenefits = [ { icon: moneyIcon, title: "Saving Money", - body: "Air source heat pumps (ASHPs) can reduce electricity usage for heating by up to 50% compared to electrical furnaces and baseboard heaters (source). For cooling, ASHPs are roughly equivalent to “central air conditioning” and far more efficient than window AC units. Together, this can translate into homeowner savings of 20%-40% off of their annual heating and cooling bills. To compare your system and to see how much you could save, ", + body: "Air source heat pumps (ASHPs) can reduce electricity usage for heating by up to 50% compared to electrical furnaces and baseboard heaters (", + bodyLink: + "https://www.amerenmissourisavings.com/hvac-air-source-heat-pump-education-flyer/", + body2: + "). For cooling, ASHPs are roughly equivalent to “central air conditioning” and far more efficient than window AC units. Together, this can translate into homeowner savings of 20%-40% off of their annual heating and cooling bills. To compare your system and to see how much you could save, ", link: "https://www.masssave.com/residential/heating-comparison-calculator", }, { icon: snowSunIcon, title: "Improved Heating & Cooling", body: "Heat pumps are an excellent way to heat and cool your home. They’re nearly silent, draw less electricity, and they are continuous: heat pumps’ continuous, low-level operation provides constant heating or cooling, eliminating the blasts of hot or cold that legacy systems usually create. To learn more about ASHP operation and benefits, ", + bodyLink: "", link: "https://goclean.masscec.com/clean-energy-solutions/air-source-heat-pumps", }, { icon: communityIcon, title: "Strengthening Community", body: "Boston residents want to stay in their homes and keep their communities strong, even while facing challenges from rising costs. Switching to heat pumps can lower utility costs, reducing the financial challenge of staying in the community. By also adding active cooling capacity, ASHPs also improve the “housing resiliency” of entire neighborhoods as annual temperatures rise. With both energy bills and temperatures on the rise, housing resiliency is more important than ever to empower communities to stay strong and stay together. To learn more, ", + bodyLink: "", link: "https://www.energy.gov/policy/articles/heat-pumps-keep-homes-warm-and-bills-low-winter", }, { icon: heatIcon, title: "Reducing Carbon Emissions", body: "Heat pumps are highly efficient heating and cooling systems that are electrically-powered. As such, they become “cleaner” whenever the source of their electric power becomes cleaner. Gas or oil fueled heating/cooling cannot benefit in the same way. How much of a difference will switching to ASHPs make in your case? Find specifics on the climate impact of a switch to heat pumps, ", + bodyLink: "", link: "https://goclean.masscec.com/clean-energy-solutions/", }, ]; @@ -50,7 +56,6 @@ const cardBenefits = [ const BenefitsHeatPumps = () => { const theme = useTheme(); const isSmallerThanSm = useMediaQuery(theme.breakpoints.down("sm")); - const isSmallerThanSmm = useMediaQuery(theme.breakpoints.down("smm")); return ( { - {/* - {isSmallerThanSmm ? ( - - ) : ( - <> - - - - )} - */} {cardBenefits.map((card) => ( @@ -105,6 +97,26 @@ const BenefitsHeatPumps = () => { {card.body} + {card.bodyLink !== "" && ( + <> + + source + + {card.body2} + + )} {card.link !== "" && ( Date: Tue, 15 Aug 2023 21:53:51 -0400 Subject: [PATCH 17/41] Try for Deployment to OpenShift --- backend/Dockerfile | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index 4dadf9e9..c20a9118 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,15 +1,17 @@ # syntax=docker/dockerfile:1 FROM ruby:3.1.3-alpine RUN apk update && apk upgrade && apk add build-base libpq-dev postgresql-client gcompat tzdata +RUN adduser rails root +USER rails WORKDIR /usr/src/app -# path context is the repo root -COPY backend/Gemfile backend/Gemfile.lock ./ +COPY Gemfile Gemfile.lock ./ + +RUN chmod -R 775 /usr/src/app +RUN chown -R rails:root /usr/src/app # add x86_64 for support on ARM platform - nokogiri expects x86 for distribution RUN bundle lock --add-platform x86_64-linux RUN bundle install -COPY ./backend . -COPY ./data-analysis/* /usr/src/data-analysis/ EXPOSE 3000 RUN chmod +x start.sh From 343baea0c1044823d89a5786cf67a23a1dc71894 Mon Sep 17 00:00:00 2001 From: Matthew Zagaja Date: Tue, 15 Aug 2023 22:01:09 -0400 Subject: [PATCH 18/41] ADD USER RIGHT NOW --- backend/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index c20a9118..b2f1fd65 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,7 +1,7 @@ # syntax=docker/dockerfile:1 FROM ruby:3.1.3-alpine RUN apk update && apk upgrade && apk add build-base libpq-dev postgresql-client gcompat tzdata -RUN adduser rails root +RUN adduser -S rails -G root USER rails WORKDIR /usr/src/app COPY Gemfile Gemfile.lock ./ From cec7f484e0b7418394443cd26edca9a996f9c4c1 Mon Sep 17 00:00:00 2001 From: Matthew Zagaja Date: Tue, 15 Aug 2023 22:03:33 -0400 Subject: [PATCH 19/41] Fix Copy --- backend/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index b2f1fd65..7a66d061 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -4,7 +4,7 @@ RUN apk update && apk upgrade && apk add build-base libpq-dev postgresql-client RUN adduser -S rails -G root USER rails WORKDIR /usr/src/app -COPY Gemfile Gemfile.lock ./ +COPY backend/Gemfile backend/Gemfile.lock ./ RUN chmod -R 775 /usr/src/app RUN chown -R rails:root /usr/src/app From 5b495734ef9b17f4a147099dfea9985eb1835684 Mon Sep 17 00:00:00 2001 From: Matthew Zagaja Date: Tue, 15 Aug 2023 22:07:39 -0400 Subject: [PATCH 20/41] Third Time is the Charm --- backend/Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index 7a66d061..cd987bfe 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -2,12 +2,13 @@ FROM ruby:3.1.3-alpine RUN apk update && apk upgrade && apk add build-base libpq-dev postgresql-client gcompat tzdata RUN adduser -S rails -G root +RUN chmod -R 775 /usr/src/app +RUN chown -R rails:root /usr/src/app + USER rails WORKDIR /usr/src/app COPY backend/Gemfile backend/Gemfile.lock ./ -RUN chmod -R 775 /usr/src/app -RUN chown -R rails:root /usr/src/app # add x86_64 for support on ARM platform - nokogiri expects x86 for distribution RUN bundle lock --add-platform x86_64-linux RUN bundle install From 16f8c142b3a2298cc6d16dec67f472a1a2a2078f Mon Sep 17 00:00:00 2001 From: Matthew Zagaja Date: Tue, 15 Aug 2023 22:09:21 -0400 Subject: [PATCH 21/41] =?UTF-8?q?4=20Try=20Matt=20They=E2=80=99ll=20Call?= =?UTF-8?q?=20Me?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index cd987bfe..f0ca4714 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -2,11 +2,11 @@ FROM ruby:3.1.3-alpine RUN apk update && apk upgrade && apk add build-base libpq-dev postgresql-client gcompat tzdata RUN adduser -S rails -G root +WORKDIR /usr/src/app RUN chmod -R 775 /usr/src/app RUN chown -R rails:root /usr/src/app USER rails -WORKDIR /usr/src/app COPY backend/Gemfile backend/Gemfile.lock ./ # add x86_64 for support on ARM platform - nokogiri expects x86 for distribution From 9a3d51593191bc0c17ef025d27f2914eebe10bd0 Mon Sep 17 00:00:00 2001 From: Matthew Zagaja Date: Tue, 15 Aug 2023 22:18:22 -0400 Subject: [PATCH 22/41] Stay On Target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don’t need to make this executable since the other change does this for us now. --- backend/Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index f0ca4714..3cd4e1cc 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -14,6 +14,5 @@ RUN bundle lock --add-platform x86_64-linux RUN bundle install EXPOSE 3000 -RUN chmod +x start.sh ENTRYPOINT ["sh", "start.sh"] From 7e77faae361fa538a052214c0eec4ea2ec15f587 Mon Sep 17 00:00:00 2001 From: Matthew Zagaja Date: Tue, 15 Aug 2023 22:34:30 -0400 Subject: [PATCH 23/41] COPY Backend Directory --- backend/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index 3cd4e1cc..16d244d0 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -2,12 +2,12 @@ FROM ruby:3.1.3-alpine RUN apk update && apk upgrade && apk add build-base libpq-dev postgresql-client gcompat tzdata RUN adduser -S rails -G root +COPY backend/ /usr/src/app/ WORKDIR /usr/src/app RUN chmod -R 775 /usr/src/app RUN chown -R rails:root /usr/src/app USER rails -COPY backend/Gemfile backend/Gemfile.lock ./ # add x86_64 for support on ARM platform - nokogiri expects x86 for distribution RUN bundle lock --add-platform x86_64-linux From 7eb4d190c2b586f56dae37e246f42dbd1d91fcbf Mon Sep 17 00:00:00 2001 From: "Efrain A. Davila" <105945226+EfrainAD@users.noreply.github.com> Date: Mon, 7 Aug 2023 19:59:19 -0400 Subject: [PATCH 24/41] Feature: The 'Completed' column is now presented as a button if the answer is yes. When clicked, it navigates the user to the survey. 1. I utilized the useGetSurveyVisitsQuery to retrieve all survey data. 2. Within the "Completed" column, I replaced the 'Yes' response with a button that facilitates user navigation to the survey. 3. Next, I regenerated the house data by appending completed: true and survey_id: visit.id. Please note that currently, the built-in method for searching survey visits by quiries is on the to-do list, according to https://docs.google.com/document/d/1QAek7K-pvnCJe4wxm38QdPCbszEE-esw3w-tuhEtMDQ/edit. So, I couldn't directly retrieve it. 4. Should any errors arise from survey visits, a CustomSnackbar is triggered to inform the user. However, the table still loads without interruption. --- frontend/front/src/pages/Admin/home/HomeTable.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/frontend/front/src/pages/Admin/home/HomeTable.js b/frontend/front/src/pages/Admin/home/HomeTable.js index 6f3a426c..d1540536 100644 --- a/frontend/front/src/pages/Admin/home/HomeTable.js +++ b/frontend/front/src/pages/Admin/home/HomeTable.js @@ -13,8 +13,15 @@ import { useGetSurveyVisitsQuery, } from "../../../api/apiSlice"; import { useNavigate } from "react-router-dom"; + import { ADMIN_HOME, withAdminPrefix } from "../../../routing/routes"; +import { + useGetHomesQuery, + useGetSurveyVisitsQuery, +} from "../../../api/apiSlice"; +import { useNavigate } from "react-router-dom"; + // Formats addresses export const getAddress = (params) => { let unit_number = ""; @@ -81,7 +88,7 @@ const HomeTable = () => { size="small" onClick={() => handleUserLink(params.row.survey_id)} > - Yes + Yes ✅ ) : ( "No" From bcc58035b6193ef5c24a630617c2df06e600c498 Mon Sep 17 00:00:00 2001 From: "Efrain A. Davila" <105945226+EfrainAD@users.noreply.github.com> Date: Sat, 19 Aug 2023 22:23:14 -0400 Subject: [PATCH 25/41] Optimization: Improve efficiency by introducing homeIdToSurveyVisitIdMap and remove the mapping of every home --- .../front/src/pages/Admin/home/HomeTable.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/frontend/front/src/pages/Admin/home/HomeTable.js b/frontend/front/src/pages/Admin/home/HomeTable.js index d1540536..d84da798 100644 --- a/frontend/front/src/pages/Admin/home/HomeTable.js +++ b/frontend/front/src/pages/Admin/home/HomeTable.js @@ -16,12 +16,6 @@ import { useNavigate } from "react-router-dom"; import { ADMIN_HOME, withAdminPrefix } from "../../../routing/routes"; -import { - useGetHomesQuery, - useGetSurveyVisitsQuery, -} from "../../../api/apiSlice"; -import { useNavigate } from "react-router-dom"; - // Formats addresses export const getAddress = (params) => { let unit_number = ""; @@ -44,7 +38,10 @@ const HomeTable = () => { ); const handleHomeLink = (home) => goToBreadcrumb("home", home); - const handleUserLink = (visit) => navigate("/admin/survey/visit/" + visit); + + const handleUserLink = (home) => { + navigate("/admin/survey/visit/" + homeIdToSurveyVisitIdMap[home.id]); + }; const handleAssignmentLink = (assignment) => goToBreadcrumb("assignment", assignment); @@ -86,7 +83,7 @@ const HomeTable = () => { sx={{ minWidth: "unset", padding: "0px" }} color="primary" size="small" - onClick={() => handleUserLink(params.row.survey_id)} + onClick={() => handleUserLink(params.row)} > Yes ✅ @@ -140,6 +137,12 @@ const HomeTable = () => { isLoading: isSurveyVisitsDataLoading, } = useGetSurveyVisitsQuery(); + const homeIdToSurveyVisitIdMap = surveyVisitsData + ? surveyVisitsData.reduce((acc, visit) => { + return { ...acc, [visit.home_id]: visit.id }; + }, {}) + : {}; + const isDataReady = !isHomesDataLoading && !isSurveyVisitsDataLoading && homesData; From 9b1832bfd329b9a6c46f20fbae614cac9d7e53ab Mon Sep 17 00:00:00 2001 From: Matt DelSordo Date: Tue, 25 Jul 2023 22:20:08 -0400 Subject: [PATCH 26/41] 438: query survey_visits to mark things completed This isn't 100% what we want, since it can't check the survey_responses on the survey_visits. Should be removed pending #405. --- .../front/src/hooks/useHomesWithCompleted.js | 38 +++++++++++++++++++ .../src/pages/Admin/assignment/AssignTable.js | 8 ++-- .../front/src/pages/Admin/home/HomeTable.js | 21 ++++++++++ .../src/pages/Surveyor/dashboard/ListView.js | 13 +++++-- 4 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 frontend/front/src/hooks/useHomesWithCompleted.js diff --git a/frontend/front/src/hooks/useHomesWithCompleted.js b/frontend/front/src/hooks/useHomesWithCompleted.js new file mode 100644 index 00000000..804c6fd3 --- /dev/null +++ b/frontend/front/src/hooks/useHomesWithCompleted.js @@ -0,0 +1,38 @@ +import { useMemo } from "react"; +import { useGetSurveyVisitsQuery } from "../api/apiSlice"; + +/** + * Workaround until https://github.com/codeforboston/urban-league-heat-pump-accelerator/pull/405 is merged + */ + +export const setHomesCompleted = (homes, surveyVisits) => + (homes || []).map((home) => ({ + ...home, + completed: !!surveyVisits?.find((sv) => sv.home_id === home.id), + })); + +export const useHomesWithCompleted = (homes) => { + const { data: surveyVisits } = useGetSurveyVisitsQuery(); + + return useMemo( + () => setHomesCompleted(homes, surveyVisits), + [homes, surveyVisits] + ); +}; + +export const useAssignmentsWithCompleted = (assignments) => { + const { data: surveyVisits } = useGetSurveyVisitsQuery(); + + return useMemo( + () => + (assignments || []).map((a) => { + const newHomes = setHomesCompleted(a.homes, surveyVisits); + return { + ...a, + homes: newHomes, + completed: a.homes.every((h) => h.completed === true), + }; + }), + [assignments, surveyVisits] + ); +}; diff --git a/frontend/front/src/pages/Admin/assignment/AssignTable.js b/frontend/front/src/pages/Admin/assignment/AssignTable.js index 4cd00d9f..58d3d880 100644 --- a/frontend/front/src/pages/Admin/assignment/AssignTable.js +++ b/frontend/front/src/pages/Admin/assignment/AssignTable.js @@ -51,17 +51,19 @@ const AssignTable = () => { isLoading: isSurveyorsDataLoading, } = useGetSurveyorsQuery(); + const assignmentsWithCompleted = useAssignmentsWithCompleted(assignmentsData); + const tableData = useMemo( () => - assignmentsData && surveyorsData - ? assignmentsData.map((a) => ({ + assignmentsWithCompleted && surveyorsData + ? assignmentsWithCompleted.map((a) => ({ ...a, surveyorData: a.surveyor_ids.map((id) => surveyorsData.find((s) => s.id === id) ), })) : [], - [assignmentsData, surveyorsData] + [assignmentsWithCompleted, surveyorsData] ); const [ diff --git a/frontend/front/src/pages/Admin/home/HomeTable.js b/frontend/front/src/pages/Admin/home/HomeTable.js index d84da798..b78291da 100644 --- a/frontend/front/src/pages/Admin/home/HomeTable.js +++ b/frontend/front/src/pages/Admin/home/HomeTable.js @@ -76,6 +76,7 @@ const HomeTable = () => { { field: "completed", headerName: "Completed", +<<<<<<< HEAD renderCell: (params) => params.row.completed === true ? ( + + ), }, { field: "zip_code", @@ -100,22 +114,6 @@ const AssignProfile = () => { ), }, - { - field: "hid", - headerName: "Home", - minWidth: 50, - maxWidth: 80, - renderCell: (params) => ( - - ), - }, { field: "unassign", headerName: "Unassign", @@ -154,25 +152,29 @@ const AssignProfile = () => { /> ) : ( - Assigned Surveyor(s): - {surveyors.map((surveyor) => ( - - ))} - + + {surveyors.map((surveyor) => ( + + ))} + +
{ const handleUserLink = (user) => goToBreadcrumb("user", user); - const handleAssignmentLink = (assignment) => + const handleAssignmentLink = (assignment) => { goToBreadcrumb("assignment", assignment); - + }; // DataGrid columns const columns = [ - { field: "id", headerName: "Assign. Id", maxWidth: 100, flex: 1 }, { - field: "assignment", - headerName: "Assignment", - minWidth: 110, + field: "id", + headerName: "Id #", + maxWidth: 50, flex: 1, renderCell: (params) => ( ), }, + { + field: "surveyorData", + headerName: "Surveyor(s)", + flex: 1, + renderCell: (params) => { + return params.row.surveyorData ? ( + + {params.row.surveyorData.map((surveyor) => { + return ( + + ); + })} + + ) : ( + "Unassigned" + ); + }, + }, { field: "completed", headerName: "Completion", - width: 110, + width: "min-content", + maxWidth: 110, flex: 1, renderCell: (params) => { let completed = 0; @@ -142,26 +175,6 @@ const AssignTable = () => { }`; }, }, - { - field: "surveyorData", - headerName: "Surveyor(s)", - width: 150, - flex: 1, - renderCell: (params) => { - return params.row.surveyorData - ? params.row.surveyorData.map((surveyor) => { - return ( - - ); - }) - : "Unassigned"; - }, - }, ]; return ( @@ -187,7 +200,12 @@ const AssignTable = () => { )} - + Surveyor @@ -206,12 +224,18 @@ const AssignTable = () => { - - + + + + { columns={columns} pageSize={20} rowsPerPageOptions={[20]} + getRowHeight={() => "auto"} disableSelectionOnClick autoHeight checkboxSelection diff --git a/frontend/front/src/pages/Admin/home/Home.js b/frontend/front/src/pages/Admin/home/Home.js index 9ca0ed31..1d7e1cf6 100644 --- a/frontend/front/src/pages/Admin/home/Home.js +++ b/frontend/front/src/pages/Admin/home/Home.js @@ -1,4 +1,4 @@ -import { Box, Button, IconButton, TextField } from "@mui/material"; +import { Box, Button, IconButton, Stack, TextField } from "@mui/material"; import AddIcon from "@mui/icons-material/Add"; import ContainerTitle from "../component/ContainerTitle"; @@ -10,29 +10,33 @@ import SearchIcon from "@mui/icons-material/Search"; const Home = () => { return ( - - + + - - - - + + diff --git a/frontend/front/src/pages/Admin/home/HomeProfile.js b/frontend/front/src/pages/Admin/home/HomeProfile.js index 5d33f7ff..eb8d9073 100644 --- a/frontend/front/src/pages/Admin/home/HomeProfile.js +++ b/frontend/front/src/pages/Admin/home/HomeProfile.js @@ -76,7 +76,7 @@ const HomeProfile = () => { /> ) : ( <> - + Home Profile: {hid} diff --git a/frontend/front/src/pages/Admin/home/HomeTable.js b/frontend/front/src/pages/Admin/home/HomeTable.js index d84da798..c3cdcb62 100644 --- a/frontend/front/src/pages/Admin/home/HomeTable.js +++ b/frontend/front/src/pages/Admin/home/HomeTable.js @@ -56,8 +56,23 @@ const HomeTable = () => { field: "address", valueGetter: getAddress, headerName: "Address", - minWidth: 200, - flex: 1, + minWidth: 300, + // maxWidth: 300, + // flex: 1.5, + renderCell: (params) => ( + + + + ), }, { field: "city", @@ -109,21 +124,6 @@ const HomeTable = () => { headerName: "Assignment", width: 110, }, - { - field: "home", - renderCell: (params) => ( - - ), - headerName: "Home", - maxWidth: 80, - }, ]; const { diff --git a/frontend/front/src/pages/Admin/nav/Nav.js b/frontend/front/src/pages/Admin/nav/Nav.js index decde38f..23114c2b 100644 --- a/frontend/front/src/pages/Admin/nav/Nav.js +++ b/frontend/front/src/pages/Admin/nav/Nav.js @@ -16,7 +16,12 @@ const Nav = () => { SURVEYOR MODE - diff --git a/frontend/front/src/pages/Admin/user/UserProfile.js b/frontend/front/src/pages/Admin/user/UserProfile.js index 89bb4817..d6a7bcc8 100644 --- a/frontend/front/src/pages/Admin/user/UserProfile.js +++ b/frontend/front/src/pages/Admin/user/UserProfile.js @@ -113,7 +113,7 @@ const UserProfile = () => { title="Confirm Delete" message="Please confirm to delete this user." /> - + User Profile: {uid} {/* Could add user ID to header. */} diff --git a/frontend/front/src/pages/Public/Assets/adminTheme.js b/frontend/front/src/pages/Public/Assets/adminTheme.js new file mode 100644 index 00000000..26295145 --- /dev/null +++ b/frontend/front/src/pages/Public/Assets/adminTheme.js @@ -0,0 +1,19 @@ +import { createTheme, responsiveFontSizes } from "@mui/material"; + +/* The custom colors palette is located in the Index.css file. */ + +let adminTheme = createTheme({ + breakpoints: { + values: { + xs: 0, + xxs: 330, // Custom breakpoint + smm: 450, // Custom breakpoint + sm: 600, + md: 960, + lg: 1280, + xl: 1920, + }, + }, +}); + +export default responsiveFontSizes(adminTheme); diff --git a/frontend/front/yarn.lock b/frontend/front/yarn.lock index e9e79865..a47bd893 100644 --- a/frontend/front/yarn.lock +++ b/frontend/front/yarn.lock @@ -10135,4 +10135,4 @@ yargs@^16.2.0: yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== \ No newline at end of file From 0305355f927e962bee8a3fc73089022ed3c0cb89 Mon Sep 17 00:00:00 2001 From: Matt DelSordo Date: Tue, 15 Aug 2023 21:11:31 -0400 Subject: [PATCH 29/41] 455: return survey answers in survey visit response --- .../app/views/survey_visits/_survey_visit.json.jbuilder | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/backend/app/views/survey_visits/_survey_visit.json.jbuilder b/backend/app/views/survey_visits/_survey_visit.json.jbuilder index 72b9169c..380e8e8a 100644 --- a/backend/app/views/survey_visits/_survey_visit.json.jbuilder +++ b/backend/app/views/survey_visits/_survey_visit.json.jbuilder @@ -2,3 +2,12 @@ json.extract! survey_visit, :id, :surveyor_id, :home_id, :created_at, :updated_at json.url survey_visit_url(survey_visit, format: :json) +json.survey_response do + json.id survey_visit.survey_response.id + json.survey_id survey_visit.survey_response.survey_id + json.survey_answers survey_visit.survey_response.survey_answers do |sa| + json.id sa.id + json.survey_question_id sa.survey_question_id + json.answer sa.answer + end +end From 4effd6abd40d2bea96c13a81474a8913068837d8 Mon Sep 17 00:00:00 2001 From: Matt DelSordo Date: Tue, 15 Aug 2023 21:14:44 -0400 Subject: [PATCH 30/41] appease prettier --- frontend/front/src/pages/Public/Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/front/src/pages/Public/Readme.md b/frontend/front/src/pages/Public/Readme.md index 5fd7cfa1..797892c5 100644 --- a/frontend/front/src/pages/Public/Readme.md +++ b/frontend/front/src/pages/Public/Readme.md @@ -25,4 +25,4 @@ - As an authorized user, I want to be able to login. - As an authorized user, I want to be able to change my password. - As an authorized user, I want to be able to login/logout successfully. -- As an authorized user, I am not able to create new users \ No newline at end of file +- As an authorized user, I am not able to create new users From fd2f67beaf6c50390db648c318412707880d03ab Mon Sep 17 00:00:00 2001 From: Matt DelSordo Date: Thu, 17 Aug 2023 16:54:44 -0400 Subject: [PATCH 31/41] add survey_visit_ids to home response This will make linking between homes and survey_visits on the admin homes table a lot easier. Elsewhere we can filter survey_visits on home_id. --- backend/app/views/homes/_home.json.jbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/app/views/homes/_home.json.jbuilder b/backend/app/views/homes/_home.json.jbuilder index 0ef6d611..ab3ae7e4 100644 --- a/backend/app/views/homes/_home.json.jbuilder +++ b/backend/app/views/homes/_home.json.jbuilder @@ -1,7 +1,7 @@ # frozen_string_literal: true json.extract! home, :id, :street_number, :street_name, :unit_number, :city, :state, :zip_code, :building_type, - :assignment_id, :visit_order, :latitude, :longitude + :assignment_id, :visit_order, :latitude, :longitude, :survey_visit_ids json.visited home.visited? json.completed home.completed? json.url home_url(home, format: :json) From 89bc727a3756cee373ffd7b19e199572d92adbfa Mon Sep 17 00:00:00 2001 From: "Efrain A. Davila" <105945226+EfrainAD@users.noreply.github.com> Date: Mon, 7 Aug 2023 19:59:19 -0400 Subject: [PATCH 32/41] Feature: The 'Completed' column is now presented as a button if the answer is yes. When clicked, it navigates the user to the survey. 1. I utilized the useGetSurveyVisitsQuery to retrieve all survey data. 2. Within the "Completed" column, I replaced the 'Yes' response with a button that facilitates user navigation to the survey. 3. Next, I regenerated the house data by appending completed: true and survey_id: visit.id. Please note that currently, the built-in method for searching survey visits by quiries is on the to-do list, according to https://docs.google.com/document/d/1QAek7K-pvnCJe4wxm38QdPCbszEE-esw3w-tuhEtMDQ/edit. So, I couldn't directly retrieve it. 4. Should any errors arise from survey visits, a CustomSnackbar is triggered to inform the user. However, the table still loads without interruption. --- frontend/front/src/pages/Admin/home/HomeTable.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frontend/front/src/pages/Admin/home/HomeTable.js b/frontend/front/src/pages/Admin/home/HomeTable.js index c3cdcb62..3fc66fb3 100644 --- a/frontend/front/src/pages/Admin/home/HomeTable.js +++ b/frontend/front/src/pages/Admin/home/HomeTable.js @@ -15,6 +15,11 @@ import { import { useNavigate } from "react-router-dom"; import { ADMIN_HOME, withAdminPrefix } from "../../../routing/routes"; +import { + useGetHomesQuery, + useGetSurveyVisitsQuery, +} from "../../../api/apiSlice"; +import { useNavigate } from "react-router-dom"; // Formats addresses export const getAddress = (params) => { From d81216a2ee1453d64bc46332daecd9c59ae708b8 Mon Sep 17 00:00:00 2001 From: Matt DelSordo Date: Tue, 25 Jul 2023 22:20:08 -0400 Subject: [PATCH 33/41] This trying fix my branch 438: query survey_visits to mark things completed This isn't 100% what we want, since it can't check the survey_responses on the survey_visits. Should be removed pending #405. --- .../front/src/hooks/useHomesWithCompleted.js | 38 +++++++++++++++++++ .../src/pages/Admin/assignment/AssignTable.js | 29 ++++++++++++-- .../src/pages/Surveyor/dashboard/ListView.js | 13 +++++-- 3 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 frontend/front/src/hooks/useHomesWithCompleted.js diff --git a/frontend/front/src/hooks/useHomesWithCompleted.js b/frontend/front/src/hooks/useHomesWithCompleted.js new file mode 100644 index 00000000..804c6fd3 --- /dev/null +++ b/frontend/front/src/hooks/useHomesWithCompleted.js @@ -0,0 +1,38 @@ +import { useMemo } from "react"; +import { useGetSurveyVisitsQuery } from "../api/apiSlice"; + +/** + * Workaround until https://github.com/codeforboston/urban-league-heat-pump-accelerator/pull/405 is merged + */ + +export const setHomesCompleted = (homes, surveyVisits) => + (homes || []).map((home) => ({ + ...home, + completed: !!surveyVisits?.find((sv) => sv.home_id === home.id), + })); + +export const useHomesWithCompleted = (homes) => { + const { data: surveyVisits } = useGetSurveyVisitsQuery(); + + return useMemo( + () => setHomesCompleted(homes, surveyVisits), + [homes, surveyVisits] + ); +}; + +export const useAssignmentsWithCompleted = (assignments) => { + const { data: surveyVisits } = useGetSurveyVisitsQuery(); + + return useMemo( + () => + (assignments || []).map((a) => { + const newHomes = setHomesCompleted(a.homes, surveyVisits); + return { + ...a, + homes: newHomes, + completed: a.homes.every((h) => h.completed === true), + }; + }), + [assignments, surveyVisits] + ); +}; diff --git a/frontend/front/src/pages/Admin/assignment/AssignTable.js b/frontend/front/src/pages/Admin/assignment/AssignTable.js index cf65ce32..49cd91e6 100644 --- a/frontend/front/src/pages/Admin/assignment/AssignTable.js +++ b/frontend/front/src/pages/Admin/assignment/AssignTable.js @@ -18,6 +18,7 @@ import InputLabel from "@mui/material/InputLabel"; import Loader from "../../../components/Loader"; import Select from "@mui/material/Select"; import { ADMIN_ASSIGNMENT, withAdminPrefix } from "../../../routing/routes"; +import { useAssignmentsWithCompleted } from "../../../hooks/useHomesWithCompleted"; const AssignTable = () => { const goToBreadcrumb = useGoToBreadcrumb(); @@ -51,17 +52,19 @@ const AssignTable = () => { isLoading: isSurveyorsDataLoading, } = useGetSurveyorsQuery(); + const assignmentsWithCompleted = useAssignmentsWithCompleted(assignmentsData); + const tableData = useMemo( () => - assignmentsData && surveyorsData - ? assignmentsData.map((a) => ({ + assignmentsWithCompleted && surveyorsData + ? assignmentsWithCompleted.map((a) => ({ ...a, surveyorData: a.surveyor_ids.map((id) => surveyorsData.find((s) => s.id === id) ), })) : [], - [assignmentsData, surveyorsData] + [assignmentsWithCompleted, surveyorsData] ); const [ @@ -175,6 +178,26 @@ const AssignTable = () => { }`; }, }, + { + field: "surveyorData", + headerName: "Surveyor(s)", + width: 150, + flex: 1, + renderCell: (params) => { + return params.row.surveyorData + ? params.row.surveyorData.map((surveyor) => { + return ( + + ); + }) + : "Unassigned"; + }, + }, ]; return ( diff --git a/frontend/front/src/pages/Surveyor/dashboard/ListView.js b/frontend/front/src/pages/Surveyor/dashboard/ListView.js index 908ab8f1..e92bd1ec 100644 --- a/frontend/front/src/pages/Surveyor/dashboard/ListView.js +++ b/frontend/front/src/pages/Surveyor/dashboard/ListView.js @@ -10,6 +10,7 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import Loader from "../../../components/Loader"; import { useAssignmentsForCurrentUser } from "../../../hooks/useDataForSurveyor"; import { useSearchParams } from "react-router-dom"; +import { useAssignmentsWithCompleted } from "../../../hooks/useHomesWithCompleted"; const ListView = () => { const { @@ -18,14 +19,18 @@ const ListView = () => { error: isAssignmentsError, } = useAssignmentsForCurrentUser(); + const assignmentsWithCompleted = useAssignmentsWithCompleted(assignmentsData); + const [openAccordion, setOpenAccordion] = useState(); const [searchParams] = useSearchParams(); // open the accordion of the first incomplete assignment when the page opens useEffect(() => { - setOpenAccordion((assignmentsData || []).find((a) => !a.completed)?.id); - }, [assignmentsData]); + setOpenAccordion( + (assignmentsWithCompleted || []).find((a) => !a.completed)?.id + ); + }, [assignmentsWithCompleted]); return ( @@ -49,12 +54,12 @@ const ListView = () => { Your Assignments - {(!assignmentsData || assignmentsData.length === 0) && ( + {(!assignmentsWithCompleted || assignmentsData.length === 0) && ( No assignments found. )} - {assignmentsData?.map((item, i) => { + {assignmentsWithCompleted?.map((item, i) => { return ( Date: Thu, 10 Aug 2023 17:29:43 -0400 Subject: [PATCH 34/41] 438: actually integrate with completed field --- .../front/src/hooks/useHomesWithCompleted.js | 38 ------------------- .../src/pages/Admin/assignment/AssignTable.js | 9 ++--- .../src/pages/Surveyor/dashboard/ListView.js | 13 ++----- 3 files changed, 7 insertions(+), 53 deletions(-) delete mode 100644 frontend/front/src/hooks/useHomesWithCompleted.js diff --git a/frontend/front/src/hooks/useHomesWithCompleted.js b/frontend/front/src/hooks/useHomesWithCompleted.js deleted file mode 100644 index 804c6fd3..00000000 --- a/frontend/front/src/hooks/useHomesWithCompleted.js +++ /dev/null @@ -1,38 +0,0 @@ -import { useMemo } from "react"; -import { useGetSurveyVisitsQuery } from "../api/apiSlice"; - -/** - * Workaround until https://github.com/codeforboston/urban-league-heat-pump-accelerator/pull/405 is merged - */ - -export const setHomesCompleted = (homes, surveyVisits) => - (homes || []).map((home) => ({ - ...home, - completed: !!surveyVisits?.find((sv) => sv.home_id === home.id), - })); - -export const useHomesWithCompleted = (homes) => { - const { data: surveyVisits } = useGetSurveyVisitsQuery(); - - return useMemo( - () => setHomesCompleted(homes, surveyVisits), - [homes, surveyVisits] - ); -}; - -export const useAssignmentsWithCompleted = (assignments) => { - const { data: surveyVisits } = useGetSurveyVisitsQuery(); - - return useMemo( - () => - (assignments || []).map((a) => { - const newHomes = setHomesCompleted(a.homes, surveyVisits); - return { - ...a, - homes: newHomes, - completed: a.homes.every((h) => h.completed === true), - }; - }), - [assignments, surveyVisits] - ); -}; diff --git a/frontend/front/src/pages/Admin/assignment/AssignTable.js b/frontend/front/src/pages/Admin/assignment/AssignTable.js index 49cd91e6..b777462c 100644 --- a/frontend/front/src/pages/Admin/assignment/AssignTable.js +++ b/frontend/front/src/pages/Admin/assignment/AssignTable.js @@ -18,7 +18,6 @@ import InputLabel from "@mui/material/InputLabel"; import Loader from "../../../components/Loader"; import Select from "@mui/material/Select"; import { ADMIN_ASSIGNMENT, withAdminPrefix } from "../../../routing/routes"; -import { useAssignmentsWithCompleted } from "../../../hooks/useHomesWithCompleted"; const AssignTable = () => { const goToBreadcrumb = useGoToBreadcrumb(); @@ -52,19 +51,17 @@ const AssignTable = () => { isLoading: isSurveyorsDataLoading, } = useGetSurveyorsQuery(); - const assignmentsWithCompleted = useAssignmentsWithCompleted(assignmentsData); - const tableData = useMemo( () => - assignmentsWithCompleted && surveyorsData - ? assignmentsWithCompleted.map((a) => ({ + assignmentsData && surveyorsData + ? assignmentsData.map((a) => ({ ...a, surveyorData: a.surveyor_ids.map((id) => surveyorsData.find((s) => s.id === id) ), })) : [], - [assignmentsWithCompleted, surveyorsData] + [assignmentsData, surveyorsData] ); const [ diff --git a/frontend/front/src/pages/Surveyor/dashboard/ListView.js b/frontend/front/src/pages/Surveyor/dashboard/ListView.js index e92bd1ec..908ab8f1 100644 --- a/frontend/front/src/pages/Surveyor/dashboard/ListView.js +++ b/frontend/front/src/pages/Surveyor/dashboard/ListView.js @@ -10,7 +10,6 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import Loader from "../../../components/Loader"; import { useAssignmentsForCurrentUser } from "../../../hooks/useDataForSurveyor"; import { useSearchParams } from "react-router-dom"; -import { useAssignmentsWithCompleted } from "../../../hooks/useHomesWithCompleted"; const ListView = () => { const { @@ -19,18 +18,14 @@ const ListView = () => { error: isAssignmentsError, } = useAssignmentsForCurrentUser(); - const assignmentsWithCompleted = useAssignmentsWithCompleted(assignmentsData); - const [openAccordion, setOpenAccordion] = useState(); const [searchParams] = useSearchParams(); // open the accordion of the first incomplete assignment when the page opens useEffect(() => { - setOpenAccordion( - (assignmentsWithCompleted || []).find((a) => !a.completed)?.id - ); - }, [assignmentsWithCompleted]); + setOpenAccordion((assignmentsData || []).find((a) => !a.completed)?.id); + }, [assignmentsData]); return ( @@ -54,12 +49,12 @@ const ListView = () => { Your Assignments - {(!assignmentsWithCompleted || assignmentsData.length === 0) && ( + {(!assignmentsData || assignmentsData.length === 0) && ( No assignments found. )} - {assignmentsWithCompleted?.map((item, i) => { + {assignmentsData?.map((item, i) => { return ( Date: Sun, 23 Jul 2023 20:28:48 -0400 Subject: [PATCH 35/41] 438: replace admin dashboard with tabs --- frontend/front/src/pages/Admin/home/HomeTable.js | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/front/src/pages/Admin/home/HomeTable.js b/frontend/front/src/pages/Admin/home/HomeTable.js index 3fc66fb3..3b08af50 100644 --- a/frontend/front/src/pages/Admin/home/HomeTable.js +++ b/frontend/front/src/pages/Admin/home/HomeTable.js @@ -20,6 +20,7 @@ import { useGetSurveyVisitsQuery, } from "../../../api/apiSlice"; import { useNavigate } from "react-router-dom"; +import { ADMIN_HOME, withAdminPrefix } from "../../../routing/routes"; // Formats addresses export const getAddress = (params) => { From 9f217f70d60e210f9172bacdc758fe81c963d8f6 Mon Sep 17 00:00:00 2001 From: "Efrain A. Davila" <105945226+EfrainAD@users.noreply.github.com> Date: Sun, 20 Aug 2023 01:11:38 -0400 Subject: [PATCH 36/41] bug fix from rebase --- frontend/front/src/pages/Admin/home/HomeTable.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/frontend/front/src/pages/Admin/home/HomeTable.js b/frontend/front/src/pages/Admin/home/HomeTable.js index 3b08af50..923c1a06 100644 --- a/frontend/front/src/pages/Admin/home/HomeTable.js +++ b/frontend/front/src/pages/Admin/home/HomeTable.js @@ -8,13 +8,7 @@ import CustomSnackbar from "../../../components/CustomSnackbar"; import { DataGrid } from "@mui/x-data-grid"; import Loader from "../../../components/Loader"; import React from "react"; -import { - useGetHomesQuery, - useGetSurveyVisitsQuery, -} from "../../../api/apiSlice"; -import { useNavigate } from "react-router-dom"; -import { ADMIN_HOME, withAdminPrefix } from "../../../routing/routes"; import { useGetHomesQuery, useGetSurveyVisitsQuery, From 7d32c7950964498f7a7feaaa46f3514e142c675c Mon Sep 17 00:00:00 2001 From: "Efrain A. Davila" <105945226+EfrainAD@users.noreply.github.com> Date: Sun, 20 Aug 2023 14:59:27 -0400 Subject: [PATCH 37/41] Updated the survey visit id with the new updates to the backend --- .../front/src/pages/Admin/home/HomeTable.js | 54 +++++-------------- 1 file changed, 14 insertions(+), 40 deletions(-) diff --git a/frontend/front/src/pages/Admin/home/HomeTable.js b/frontend/front/src/pages/Admin/home/HomeTable.js index 923c1a06..92724706 100644 --- a/frontend/front/src/pages/Admin/home/HomeTable.js +++ b/frontend/front/src/pages/Admin/home/HomeTable.js @@ -9,10 +9,7 @@ import { DataGrid } from "@mui/x-data-grid"; import Loader from "../../../components/Loader"; import React from "react"; -import { - useGetHomesQuery, - useGetSurveyVisitsQuery, -} from "../../../api/apiSlice"; +import { useGetHomesQuery } from "../../../api/apiSlice"; import { useNavigate } from "react-router-dom"; import { ADMIN_HOME, withAdminPrefix } from "../../../routing/routes"; @@ -40,7 +37,7 @@ const HomeTable = () => { const handleHomeLink = (home) => goToBreadcrumb("home", home); const handleUserLink = (home) => { - navigate("/admin/survey/visit/" + homeIdToSurveyVisitIdMap[home.id]); + navigate("/admin/survey/visit/" + home.survey_visit_ids[0]); }; const handleAssignmentLink = (assignment) => @@ -128,54 +125,31 @@ const HomeTable = () => { const { data: homesData, - isError: isFetchedHomesError, + isError: isHomesError, isLoading: isHomesDataLoading, } = useGetHomesQuery(); - const { - data: surveyVisitsData, - isError: isSurveyVisitsError, - isLoading: isSurveyVisitsDataLoading, - } = useGetSurveyVisitsQuery(); - - const homeIdToSurveyVisitIdMap = surveyVisitsData - ? surveyVisitsData.reduce((acc, visit) => { - return { ...acc, [visit.home_id]: visit.id }; - }, {}) - : {}; - const isDataReady = - !isHomesDataLoading && !isSurveyVisitsDataLoading && homesData; - - if (!isDataReady) { + if (isHomesDataLoading) { return ; } return ( - {isFetchedHomesError ? ( + {isHomesError ? ( ) : ( - <> - {isSurveyVisitsError && ( - - )} - - + )} ); From 96996be8fff2482017438e7107858917b5fd01da Mon Sep 17 00:00:00 2001 From: "Efrain A. Davila" <105945226+EfrainAD@users.noreply.github.com> Date: Mon, 21 Aug 2023 23:52:00 -0400 Subject: [PATCH 38/41] PR Feedback: 1. Switch to string interpolation 2. style change that was commented on --- frontend/front/src/pages/Admin/home/HomeTable.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/front/src/pages/Admin/home/HomeTable.js b/frontend/front/src/pages/Admin/home/HomeTable.js index 92724706..9e6bc398 100644 --- a/frontend/front/src/pages/Admin/home/HomeTable.js +++ b/frontend/front/src/pages/Admin/home/HomeTable.js @@ -37,7 +37,7 @@ const HomeTable = () => { const handleHomeLink = (home) => goToBreadcrumb("home", home); const handleUserLink = (home) => { - navigate("/admin/survey/visit/" + home.survey_visit_ids[0]); + navigate(`/admin/survey/visit/${home.survey_visit_ids[0]}`); }; const handleAssignmentLink = (assignment) => @@ -89,7 +89,7 @@ const HomeTable = () => { field: "completed", headerName: "Completed", renderCell: (params) => - params.row.completed === true ? ( + params.row.completed ? ( - ); - })} - - ) : ( - "Unassigned" - ); - }, - }, - { - field: "completed", - headerName: "Completion", - width: "min-content", - maxWidth: 110, - flex: 1, - renderCell: (params) => { - let completed = 0; - params.row.homes.forEach((home) => { - if (home?.completed === true) { - completed++; - } - }); - return `${completed}/${params.row.homes.length} ${ - completed === params.row.homes.length && completed > 0 ? "✅" : "" - }`; - }, - }, ]; return ( From 8b1d3f502e5b59f19526af12b69e3cdab685e0a8 Mon Sep 17 00:00:00 2001 From: thiagobardini Date: Wed, 13 Sep 2023 12:26:01 -0400 Subject: [PATCH 40/41] Implemented the design suggestions provided by the UX team --- .../front/src/pages/Public/Assets/theme.js | 2 +- .../Public/Components/Button/ButtonWhite.js | 4 +- .../Public/Components/Typography/Heading2.js | 2 + .../Public/Components/Typography/Heading3.js | 2 + .../front/src/pages/Public/Layout/Footer.js | 38 ++++++++++++++----- .../pages/Public/Pages/BenefitsHeatPumps.js | 8 ++-- .../src/pages/Public/Pages/GetInvolved.js | 1 - .../Public/Pages/Home/CardBenefitsSection.js | 12 +++--- .../Public/Pages/Home/CardLinksSection.js | 16 ++++---- .../pages/Public/Pages/Home/CarrouselHero.js | 20 ++++++++-- .../src/pages/Public/Pages/Home/HeroPage.js | 30 ++++++++++++--- .../front/src/pages/Public/Pages/Home/Home.js | 18 ++++----- .../src/pages/Public/Pages/Home/Partners.js | 13 +++---- .../pages/Public/Pages/Home/Testimonial.js | 5 ++- 14 files changed, 113 insertions(+), 58 deletions(-) diff --git a/frontend/front/src/pages/Public/Assets/theme.js b/frontend/front/src/pages/Public/Assets/theme.js index 69fda2f9..e78c5806 100644 --- a/frontend/front/src/pages/Public/Assets/theme.js +++ b/frontend/front/src/pages/Public/Assets/theme.js @@ -18,7 +18,7 @@ const theme = createTheme({ // body body: { margin: 0, - fontWeight: 400, + // fontWeight: 400, fontSize: "16px", lineHeight: 1.5, letterSpacing: "0.00938em", diff --git a/frontend/front/src/pages/Public/Components/Button/ButtonWhite.js b/frontend/front/src/pages/Public/Components/Button/ButtonWhite.js index 4b734716..4d140051 100644 --- a/frontend/front/src/pages/Public/Components/Button/ButtonWhite.js +++ b/frontend/front/src/pages/Public/Components/Button/ButtonWhite.js @@ -14,7 +14,9 @@ const ButtonWhite = ({ text, to, children }) => { to={to} onClick={() => window.scrollTo(0, 0)} sx={{ - width: "200px", + width: "auto", + minWidth: "200px", + maxWidth: "250px", height: "50px", color: "var(--color-text-2)", background: "var(--bgColor-3)", diff --git a/frontend/front/src/pages/Public/Components/Typography/Heading2.js b/frontend/front/src/pages/Public/Components/Typography/Heading2.js index 10441919..0b181015 100644 --- a/frontend/front/src/pages/Public/Components/Typography/Heading2.js +++ b/frontend/front/src/pages/Public/Components/Typography/Heading2.js @@ -4,6 +4,7 @@ function Heading2({ text, textDecoration = "none" }) { return ( {text} diff --git a/frontend/front/src/pages/Public/Components/Typography/Heading3.js b/frontend/front/src/pages/Public/Components/Typography/Heading3.js index 6aead3bc..ac534aec 100644 --- a/frontend/front/src/pages/Public/Components/Typography/Heading3.js +++ b/frontend/front/src/pages/Public/Components/Typography/Heading3.js @@ -12,6 +12,7 @@ function Heading3({ text, icon = null, textDecoration = "none" }) { fontFamily: "var(--font-family-1)", color: "var(--color-text-2)", fontWeight: "600", + textTransform: "capitalize", }} > {text} @@ -27,6 +28,7 @@ function Heading3({ text, icon = null, textDecoration = "none" }) { textDecoration: textDecoration, textUnderlinePosition: "under", textDecorationColor: "var(--color-text-2)", + textTransform: "capitalize", }} > {text} diff --git a/frontend/front/src/pages/Public/Layout/Footer.js b/frontend/front/src/pages/Public/Layout/Footer.js index ab9813f0..1d058095 100644 --- a/frontend/front/src/pages/Public/Layout/Footer.js +++ b/frontend/front/src/pages/Public/Layout/Footer.js @@ -27,7 +27,6 @@ const footerItems = { "About Heat Pumps": { link: "about-heat-pump" }, "Benefits of Heat Pumps": { link: "benefits-heat-pump" }, "Get Involved": { link: "get-involved" }, - "Our Partners": { link: "our-partners-section" }, Testimonials: { link: "testimonial-section" }, }; @@ -36,8 +35,8 @@ const FooterWrapper = styled("div")(({ theme }) => ({ color: "var(--color-text-1)", position: "relative", "& .subtitle-footer": { - fontWeight: "bold", - textDecoration: "underline", + fontWeight: "700", + textDecoration: "none", }, })); @@ -87,7 +86,7 @@ const Footer = () => { - {/* BENEFITS OF HEAT PUMPS */} + {/* LEARN MORE */} { sx={{ color: "var(--color-text-1)", }} + primaryTypographyProps={{ + fontWeight: "300", + }} /> @@ -166,7 +168,12 @@ const Footer = () => { window.scrollTo(0, 0)} @@ -176,13 +183,16 @@ const Footer = () => { sx={{ color: "var(--color-text-1)", }} + primaryTypographyProps={{ + fontWeight: "300", + }} /> - {/* GET IN TOUCH */} + {/* CONTACT US */} { }} > <> - - Get to Know Us + + Contact Us { 617-635-4500 @@ -229,7 +243,11 @@ const Footer = () => { help@bostonhpa.org diff --git a/frontend/front/src/pages/Public/Pages/BenefitsHeatPumps.js b/frontend/front/src/pages/Public/Pages/BenefitsHeatPumps.js index 7ca1df4f..19d5d821 100644 --- a/frontend/front/src/pages/Public/Pages/BenefitsHeatPumps.js +++ b/frontend/front/src/pages/Public/Pages/BenefitsHeatPumps.js @@ -22,7 +22,7 @@ import ButtonDarkBlue from "../Components/Button/ButtonDarkBlue"; const cardBenefits = [ { icon: moneyIcon, - title: "Saving Money", + title: "Lower utility bills", body: "Air source heat pumps (ASHPs) can reduce electricity usage for heating by up to 50% compared to electrical furnaces and baseboard heaters (", bodyLink: "https://www.amerenmissourisavings.com/hvac-air-source-heat-pump-education-flyer/", @@ -32,21 +32,21 @@ const cardBenefits = [ }, { icon: snowSunIcon, - title: "Improved Heating & Cooling", + title: "Better Heating & Cooling", body: "Heat pumps are an excellent way to heat and cool your home. They’re nearly silent, draw less electricity, and they are continuous: heat pumps’ continuous, low-level operation provides constant heating or cooling, eliminating the blasts of hot or cold that legacy systems usually create. To learn more about ASHP operation and benefits, ", bodyLink: "", link: "https://goclean.masscec.com/clean-energy-solutions/air-source-heat-pumps", }, { icon: communityIcon, - title: "Strengthening Community", + title: "Stronger Communities", body: "Boston residents want to stay in their homes and keep their communities strong, even while facing challenges from rising costs. Switching to heat pumps can lower utility costs, reducing the financial challenge of staying in the community. By also adding active cooling capacity, ASHPs also improve the “housing resiliency” of entire neighborhoods as annual temperatures rise. With both energy bills and temperatures on the rise, housing resiliency is more important than ever to empower communities to stay strong and stay together. To learn more, ", bodyLink: "", link: "https://www.energy.gov/policy/articles/heat-pumps-keep-homes-warm-and-bills-low-winter", }, { icon: heatIcon, - title: "Reducing Carbon Emissions", + title: "Lower Carbon Emissions", body: "Heat pumps are highly efficient heating and cooling systems that are electrically-powered. As such, they become “cleaner” whenever the source of their electric power becomes cleaner. Gas or oil fueled heating/cooling cannot benefit in the same way. How much of a difference will switching to ASHPs make in your case? Find specifics on the climate impact of a switch to heat pumps, ", bodyLink: "", link: "https://goclean.masscec.com/clean-energy-solutions/", diff --git a/frontend/front/src/pages/Public/Pages/GetInvolved.js b/frontend/front/src/pages/Public/Pages/GetInvolved.js index 496afeaf..aec3f3a0 100644 --- a/frontend/front/src/pages/Public/Pages/GetInvolved.js +++ b/frontend/front/src/pages/Public/Pages/GetInvolved.js @@ -33,7 +33,6 @@ function GetInvolved() { mediaSource: card3, title: "Discuss with your community", body: "You can host any sort of event and share flyers about how to help your neighbors save money by getting a heat pump!", - linkDescription: "Download informational flyer", linkDownload: CommunityFlyer, }, { diff --git a/frontend/front/src/pages/Public/Pages/Home/CardBenefitsSection.js b/frontend/front/src/pages/Public/Pages/Home/CardBenefitsSection.js index 45507111..7a57925b 100644 --- a/frontend/front/src/pages/Public/Pages/Home/CardBenefitsSection.js +++ b/frontend/front/src/pages/Public/Pages/Home/CardBenefitsSection.js @@ -41,7 +41,7 @@ const CardBenefitsSection = () => { id: 2, title: "Experience The All In One Comfort", paragraphs: [ - "Heat pumps can help you keep cool in the summer and warm in the winter. They are efficient, nearly silent, and convenient, providing comfort throughout the home.", + "The same heat pump that helps to cool in the summer can then provide warmth in the winter- it's one system that is efficient, quiet, and convenient, providing comfort throughout the home.", ], image: imageTwo, buttonText: "", @@ -49,9 +49,9 @@ const CardBenefitsSection = () => { }, { id: 3, - title: "Strengthen Community", + title: "Stronger communities", paragraphs: [ - "Because heat pumps can lower your utility bills, they can help seniors and low-income residents stay in their homes longer.", + "By helping to lower utility bills, heat pumps can lower the cost of living for residents, which in turn can support residents living on fixed- or low-incomes to remain in their homes longer, strengthening communities.", ], image: strengthenCommunity, buttonText: "", @@ -59,9 +59,9 @@ const CardBenefitsSection = () => { }, { id: 4, - title: "Environmentally Friendly ", + title: "Cleaner air", paragraphs: [ - "Heat pumps use electricity that can be produced by renewable sources, making them much more eco-friendly than gas or oil-fueled systems. With a single “green-powered” unit that heats and cools, your home’s carbon footprint is as low as it can go.", + "Heat pumps use electricity that can be produced by renewable sources. As the grid becomes more green, heat pumps become much more eco-friendly than gas or oil-fueled systems. With a single “green-powered” unit that heats and cools, your home’s carbon footprint is as low as it can go.", ], image: beEnvironmentally, buttonText: "", @@ -91,7 +91,7 @@ const CardBenefitsSection = () => { variant="body" sx={{ color: "var(--color-text-3)", display: "inline-block" }} > - Learn more about + Learn more about the diff --git a/frontend/front/src/pages/Public/Pages/Home/CardLinksSection.js b/frontend/front/src/pages/Public/Pages/Home/CardLinksSection.js index 6dfcc06b..a5738799 100644 --- a/frontend/front/src/pages/Public/Pages/Home/CardLinksSection.js +++ b/frontend/front/src/pages/Public/Pages/Home/CardLinksSection.js @@ -30,7 +30,7 @@ const GridLinkWrapper = styled(Grid)(({ theme }) => ({ justifyContent: "center", flexWrap: "nowrap", gap: "2rem", - [theme.breakpoints.down("md")]: { + [theme.breakpoints.down("lg")]: { flexWrap: "wrap", }, })); @@ -39,26 +39,27 @@ const CardLinksSection = () => { const linkCards = [ { id: 1, - title: "Add Your Voice", + title: "What is a heat pump?", paragraph: - "To a collections of homeowner’s questions and thoughts about heat pumps.", + "A heat pump is an energy-efficient system that heats your home in the winter, and cools your home in the summer.", button: { text: "Take the survey", to: "survey", }, idCSS: "survey-link-section", - image: imageVoice, + image: imageAbout, }, { id: 2, title: "About Us", - paragraph: "Empowering Boston residents to save, stay, and sustain.", + paragraph: + "The Boston Heat Pump Accelerator is an initiative of the Urban League of Eastern Massachusetts, in partnership with local and national organizations.", button: { text: "Learn more", to: "about-us", }, idCSS: "learnmore-link-section", - image: imageAbout, + image: imageVoice, }, ]; @@ -72,7 +73,8 @@ const CardLinksSection = () => { background: "var(--bgColor-3)", display: "flex", flexDirection: { xs: "column", sm: "row" }, - minWidth: "260px", + width: "100%", + minWidth: { xs: "260px", lg: "634px" }, maxWidth: { xs: "468px", sm: "680px" }, borderRadius: "2%", }} diff --git a/frontend/front/src/pages/Public/Pages/Home/CarrouselHero.js b/frontend/front/src/pages/Public/Pages/Home/CarrouselHero.js index 65e0cb93..59524290 100644 --- a/frontend/front/src/pages/Public/Pages/Home/CarrouselHero.js +++ b/frontend/front/src/pages/Public/Pages/Home/CarrouselHero.js @@ -22,16 +22,28 @@ function CarrouselHero(props) { { component: ( ), }, + // component: ( + // + // ), + // }, // { // component: ( // ({ display: "flex", @@ -70,7 +71,7 @@ const HeroPage = ({ {text1} {link !== "" && ( - {textBold} - + )} {text2} - + diff --git a/frontend/front/src/pages/Public/Pages/Home/Home.js b/frontend/front/src/pages/Public/Pages/Home/Home.js index af2643e3..5049db91 100644 --- a/frontend/front/src/pages/Public/Pages/Home/Home.js +++ b/frontend/front/src/pages/Public/Pages/Home/Home.js @@ -35,28 +35,28 @@ const Home = () => { {/* TESTIMONIALS */} - + - {/* PARTNERS LOGO */} - - - - - - {/* CARDS BENEFITS */} + + {/* PARTNERS LOGO */} + + + + + ); }; diff --git a/frontend/front/src/pages/Public/Pages/Home/Partners.js b/frontend/front/src/pages/Public/Pages/Home/Partners.js index b8c4791c..4bd46900 100644 --- a/frontend/front/src/pages/Public/Pages/Home/Partners.js +++ b/frontend/front/src/pages/Public/Pages/Home/Partners.js @@ -7,7 +7,6 @@ import codeForAmericaLogo from "../../../../assets/images/partnersLogo/CFA.png"; import codeForBostonLogo from "../../../../assets/images/partnersLogo/CFB.png"; import pcb from "../../../../assets/images/partnersLogo/powercorp-boston.jpeg"; import AnimatedBox from "../../Components/AnimatedBox"; -import ButtonDarkBklue from "../../Components/Button/ButtonDarkBlue"; import Heading1 from "../../Components/Typography/Heading1"; const Partners = () => { @@ -91,22 +90,20 @@ const Partners = () => { sx={{ color: "var(--color-text-3)" }} textAlign={{ xs: "center", sm: "left" }} > - This initiative is a collaboration of Massachusetts government and - nonprofit organizations working together to help{" "} + The Boston Heat Pump Accelerator is an initiative of the Urban + League of Eastern Massachusetts, in partnership with local and + national organizations.{" "} - make heat pumps more available to low-income residents + Learn more . - - - diff --git a/frontend/front/src/pages/Public/Pages/Home/Testimonial.js b/frontend/front/src/pages/Public/Pages/Home/Testimonial.js index 6ac70ba7..63663a76 100644 --- a/frontend/front/src/pages/Public/Pages/Home/Testimonial.js +++ b/frontend/front/src/pages/Public/Pages/Home/Testimonial.js @@ -66,10 +66,11 @@ const Testimonial = () => { that again!” - + - Hear what else people have to say about their heat pumps! + Stories from other Massachusetts residents about their heat + pumps. Date: Wed, 13 Sep 2023 12:47:04 -0400 Subject: [PATCH 41/41] Text improvements --- .../front/src/pages/Public/Pages/Home/CardBenefitsSection.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/front/src/pages/Public/Pages/Home/CardBenefitsSection.js b/frontend/front/src/pages/Public/Pages/Home/CardBenefitsSection.js index 7a57925b..e0e08183 100644 --- a/frontend/front/src/pages/Public/Pages/Home/CardBenefitsSection.js +++ b/frontend/front/src/pages/Public/Pages/Home/CardBenefitsSection.js @@ -29,7 +29,7 @@ const CardBenefitsSection = () => { const cards = [ { id: 1, - title: "Saving Money", + title: "Lower energy bills", paragraphs: [ "Heat pumps are so energy efficient that they can lead to significant savings on monthly utility bills and lower maintenance, repair and replacement costs.", ], @@ -39,7 +39,7 @@ const CardBenefitsSection = () => { }, { id: 2, - title: "Experience The All In One Comfort", + title: "Comfort at home", paragraphs: [ "The same heat pump that helps to cool in the summer can then provide warmth in the winter- it's one system that is efficient, quiet, and convenient, providing comfort throughout the home.", ],