├── public ├── robots.txt ├── favicon.ico ├── favicon.png ├── social-card.png ├── files │ ├── EarningsDataErrata.pdf │ ├── College-Scorecard-Guide.pdf │ ├── College-Scorecard-Toolkit.pdf │ ├── FieldOfStudyDataDocumentation.pdf │ ├── InstitutionDataDocumentation.pdf │ ├── CollegeScorecardDataDictionary.xlsx │ ├── UsingFederalDataToMeasureAndImprovePerformance.pdf │ └── BetterInformationForBetterCollegeChoiceAndInstitutionalPerformance.pdf └── school-icons │ ├── four.svg │ ├── two.svg │ ├── certificate.svg │ ├── private.svg │ ├── profit.svg │ ├── public.svg │ ├── city.svg │ ├── small.svg │ ├── suburban.svg │ ├── town.svg │ ├── medium.svg │ └── large.svg ├── pages ├── school.vue ├── data.vue ├── search.vue ├── test.vue └── data │ ├── glossary.vue │ ├── index.vue │ └── data-documentation.vue ├── server └── tsconfig.json ├── assets ├── images │ ├── checkmark.png │ ├── hero-large.jpg │ ├── hero-small.jpg │ ├── CS-Main-Tw@2x.png │ ├── Pathways-Icon.png │ ├── VA-logo-light.png │ ├── f-grade-paper.jpg │ ├── home │ │ ├── location.png │ │ ├── school_1.png │ │ ├── school_2.png │ │ ├── search.png │ │ ├── psychology.png │ │ ├── median_debt.png │ │ ├── search_cost.png │ │ ├── search_degree.png │ │ ├── acceptance_rate.png │ │ ├── graduation_rate.png │ │ ├── median_earnings.png │ │ ├── search_location.png │ │ ├── average_annual_cost.png │ │ └── compare.svg │ ├── social-card.png │ ├── Scorecard-Preview-2022.jpg │ ├── US-DeptOfEducation-Seal.png │ ├── school-icon-pngs │ │ ├── city.png │ │ ├── large.png │ │ ├── medium.png │ │ ├── profit.png │ │ ├── public.png │ │ ├── rural.png │ │ ├── small.png │ │ ├── town.png │ │ ├── private.png │ │ └── suburban.png │ ├── Logo-Department-of-Labor.png │ ├── double-caret.svg │ ├── icon-Location.svg │ ├── icon-financial-aid-black.svg │ ├── icon-financial-aid.svg │ ├── icon-pathways.svg │ ├── icon-pathways-blue.svg │ ├── icon-Note.svg │ ├── icon-google-drive.svg │ ├── icon-docs.svg │ ├── icon-pdf.svg │ ├── icon-ppt.svg │ ├── icon-slides.svg │ ├── Pathway-Icon.svg │ ├── icon-pathways-black.svg │ ├── icon-doc.svg │ ├── icon-Financial-Aid-training.svg │ └── icon-guide.svg ├── scss │ ├── _functions.scss │ ├── _fonts.scss │ ├── _breakpoints.scss │ └── style.scss └── data │ ├── repayment_rates.json │ ├── race_ethnicity.json │ ├── special_designations.json │ ├── states.json │ └── cip_2_digit.json ├── tsconfig.json ├── plugins ├── chartjs.ts ├── focus-trap.ts └── vuetify.ts ├── middleware ├── school.js ├── fos.js └── school-search.js ├── app.vue ├── components ├── Spacer.vue ├── documentation │ ├── Card.vue │ └── Help.vue ├── RecaptchaCheckbox.vue ├── SimpleTooltip.vue ├── layout │ ├── UsaLockIcon.vue │ ├── UsaGovIcon.vue │ ├── UsaFlag.vue │ ├── WebinarCTA.vue │ ├── DataNavigation.vue │ ├── UsaBanner.vue │ ├── SearchNavigation.vue │ ├── FooterCTA.vue │ └── Subnav.vue ├── school │ ├── AddToCompare.vue │ ├── panel │ │ └── FieldOfStudyToggle.vue │ └── OutcomesConfig.vue ├── search │ ├── canned │ │ ├── Slider.vue │ │ └── Container.vue │ └── FieldAutocomplete.vue ├── Map.vue ├── home │ ├── CompareIcon.vue │ ├── Fafsa.vue │ ├── Veterans.vue │ ├── Arrow.vue │ └── Resources.vue ├── compare │ ├── FieldsOfStudy │ │ ├── NumberOfGraduates.vue │ │ ├── Data │ │ │ ├── Block.vue │ │ │ └── Section.vue │ │ ├── SalaryAfterCompleting.vue │ │ └── FinancialAid.vue │ ├── TooltipHeader.vue │ └── Schools │ │ ├── Data │ │ ├── Section.vue │ │ └── Block.vue │ │ ├── TypicalEarnings.vue │ │ └── Costs.vue ├── chart │ ├── VerticalBarMedian.vue │ ├── Donut.vue │ └── Ratio.vue └── Toggle.vue ├── composables ├── useSchoolOutcomesHelper.js ├── useNumberFormatter.js ├── useVuetify.js ├── useScroll.js ├── useApi.js ├── useRecaptcha.js ├── useSiteData.js └── useLocationCheck.js ├── .gitignore ├── error.vue ├── stores ├── banners.js ├── analytics.js └── compare.js ├── README.md ├── package.json └── nuxt.config.ts /public/robots.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /pages/school.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.nuxt/tsconfig.server.json" 3 | } 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/public/favicon.png -------------------------------------------------------------------------------- /public/social-card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/public/social-card.png -------------------------------------------------------------------------------- /assets/images/checkmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/checkmark.png -------------------------------------------------------------------------------- /assets/images/hero-large.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/hero-large.jpg -------------------------------------------------------------------------------- /assets/images/hero-small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/hero-small.jpg -------------------------------------------------------------------------------- /assets/images/CS-Main-Tw@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/CS-Main-Tw@2x.png -------------------------------------------------------------------------------- /assets/images/Pathways-Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/Pathways-Icon.png -------------------------------------------------------------------------------- /assets/images/VA-logo-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/VA-logo-light.png -------------------------------------------------------------------------------- /assets/images/f-grade-paper.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/f-grade-paper.jpg -------------------------------------------------------------------------------- /assets/images/home/location.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/home/location.png -------------------------------------------------------------------------------- /assets/images/home/school_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/home/school_1.png -------------------------------------------------------------------------------- /assets/images/home/school_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/home/school_2.png -------------------------------------------------------------------------------- /assets/images/home/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/home/search.png -------------------------------------------------------------------------------- /assets/images/social-card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/social-card.png -------------------------------------------------------------------------------- /pages/data.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pages/search.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // https://nuxt.com/docs/guide/concepts/typescript 3 | "extends": "./.nuxt/tsconfig.json" 4 | } 5 | -------------------------------------------------------------------------------- /assets/images/home/psychology.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/home/psychology.png -------------------------------------------------------------------------------- /assets/images/home/median_debt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/home/median_debt.png -------------------------------------------------------------------------------- /assets/images/home/search_cost.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/home/search_cost.png -------------------------------------------------------------------------------- /assets/images/home/search_degree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/home/search_degree.png -------------------------------------------------------------------------------- /public/files/EarningsDataErrata.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/public/files/EarningsDataErrata.pdf -------------------------------------------------------------------------------- /assets/images/home/acceptance_rate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/home/acceptance_rate.png -------------------------------------------------------------------------------- /assets/images/home/graduation_rate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/home/graduation_rate.png -------------------------------------------------------------------------------- /assets/images/home/median_earnings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/home/median_earnings.png -------------------------------------------------------------------------------- /assets/images/home/search_location.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/home/search_location.png -------------------------------------------------------------------------------- /assets/images/Scorecard-Preview-2022.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/Scorecard-Preview-2022.jpg -------------------------------------------------------------------------------- /assets/images/US-DeptOfEducation-Seal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/US-DeptOfEducation-Seal.png -------------------------------------------------------------------------------- /assets/images/school-icon-pngs/city.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/school-icon-pngs/city.png -------------------------------------------------------------------------------- /assets/images/school-icon-pngs/large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/school-icon-pngs/large.png -------------------------------------------------------------------------------- /assets/images/school-icon-pngs/medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/school-icon-pngs/medium.png -------------------------------------------------------------------------------- /assets/images/school-icon-pngs/profit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/school-icon-pngs/profit.png -------------------------------------------------------------------------------- /assets/images/school-icon-pngs/public.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/school-icon-pngs/public.png -------------------------------------------------------------------------------- /assets/images/school-icon-pngs/rural.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/school-icon-pngs/rural.png -------------------------------------------------------------------------------- /assets/images/school-icon-pngs/small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/school-icon-pngs/small.png -------------------------------------------------------------------------------- /assets/images/school-icon-pngs/town.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/school-icon-pngs/town.png -------------------------------------------------------------------------------- /assets/scss/_functions.scss: -------------------------------------------------------------------------------- 1 | @function use-theme($color-name, $opacity: 1) { 2 | @return rgba(var(--v-theme-#{$color-name}), $opacity); 3 | } -------------------------------------------------------------------------------- /public/files/College-Scorecard-Guide.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/public/files/College-Scorecard-Guide.pdf -------------------------------------------------------------------------------- /assets/images/Logo-Department-of-Labor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/Logo-Department-of-Labor.png -------------------------------------------------------------------------------- /assets/images/home/average_annual_cost.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/home/average_annual_cost.png -------------------------------------------------------------------------------- /assets/images/school-icon-pngs/private.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/school-icon-pngs/private.png -------------------------------------------------------------------------------- /assets/images/school-icon-pngs/suburban.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/assets/images/school-icon-pngs/suburban.png -------------------------------------------------------------------------------- /public/files/College-Scorecard-Toolkit.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/public/files/College-Scorecard-Toolkit.pdf -------------------------------------------------------------------------------- /public/files/FieldOfStudyDataDocumentation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/public/files/FieldOfStudyDataDocumentation.pdf -------------------------------------------------------------------------------- /public/files/InstitutionDataDocumentation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/public/files/InstitutionDataDocumentation.pdf -------------------------------------------------------------------------------- /public/files/CollegeScorecardDataDictionary.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/public/files/CollegeScorecardDataDictionary.xlsx -------------------------------------------------------------------------------- /plugins/chartjs.ts: -------------------------------------------------------------------------------- 1 | import { Chart, registerables } from 'chart.js'; 2 | 3 | export default defineNuxtPlugin(() => { 4 | Chart.register(...registerables); 5 | }) -------------------------------------------------------------------------------- /middleware/school.js: -------------------------------------------------------------------------------- 1 | export default defineNuxtRouteMiddleware((to, from) => { 2 | if (!Object.keys(to.query)[0]) { 3 | return 4 | } 5 | 6 | // return navigateTo('/') 7 | }) -------------------------------------------------------------------------------- /public/files/UsingFederalDataToMeasureAndImprovePerformance.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/public/files/UsingFederalDataToMeasureAndImprovePerformance.pdf -------------------------------------------------------------------------------- /app.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /plugins/focus-trap.ts: -------------------------------------------------------------------------------- 1 | import { defineNuxtPlugin } from '#app' 2 | import { FocusTrap } from 'focus-trap-vue' 3 | 4 | export default defineNuxtPlugin((nuxtApp) => { 5 | nuxtApp.vueApp.component('focus-trap', FocusTrap) 6 | }) -------------------------------------------------------------------------------- /public/files/BetterInformationForBetterCollegeChoiceAndInstitutionalPerformance.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RTICWDT/college-scorecard/HEAD/public/files/BetterInformationForBetterCollegeChoiceAndInstitutionalPerformance.pdf -------------------------------------------------------------------------------- /components/Spacer.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | -------------------------------------------------------------------------------- /assets/scss/_fonts.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "Inter", Helvetica, arial, sans-serif; 3 | font-style: normal; 4 | font-weight: 300; 5 | font-display: swap; 6 | src: url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 7 | } -------------------------------------------------------------------------------- /middleware/fos.js: -------------------------------------------------------------------------------- 1 | export default defineNuxtRouteMiddleware((to, from) => { 2 | if (from.name === "search-fos-landing") { 3 | if (to.query.cip4 && to.query.cip4_degree) { 4 | return 5 | } 6 | 7 | return navigateTo('/search/fos-landing/') 8 | } 9 | }) -------------------------------------------------------------------------------- /composables/useSchoolOutcomesHelper.js: -------------------------------------------------------------------------------- 1 | export const useSchoolOutcomesHelper = () => { 2 | const showPellOnly = ref(false) 3 | const options = ref({ 4 | study: 'study_both', 5 | enroll: 'enroll_both', 6 | }) 7 | 8 | return { 9 | showPellOnly, 10 | options, 11 | } 12 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Nuxt dev/build outputs 2 | .output 3 | .data 4 | .nuxt 5 | .nitro 6 | .cache 7 | dist 8 | 9 | # Node dependencies 10 | node_modules 11 | 12 | # Logs 13 | logs 14 | *.log 15 | 16 | # Misc 17 | .DS_Store 18 | .fleet 19 | .idea 20 | 21 | # Local env files 22 | .env 23 | .env.* 24 | !.env.example 25 | -------------------------------------------------------------------------------- /assets/data/repayment_rates.json: -------------------------------------------------------------------------------- 1 | { 2 | "default": "Defaulted", 3 | "deferment": "Deferment", 4 | "discharge": "Discharged", 5 | "fullypaid": "Paid in Full", 6 | "delinquent": "Delinquent", 7 | "noprogress": "Not Making Progress", 8 | "forbearance": "Forbearance", 9 | "makingprogress": "Making Progress" 10 | } 11 | -------------------------------------------------------------------------------- /assets/data/race_ethnicity.json: -------------------------------------------------------------------------------- 1 | { 2 | "aian": "American Indian/Alaska Native", 3 | "asian": "Asian", 4 | "black": "Black", 5 | "hispanic": "Hispanic", 6 | "nhpi": "Native Hawaiian/Pacific Islander", 7 | "non_resident_alien": "Non-resident alien", 8 | "two_or_more": "Two or more races", 9 | "unknown": "Unknown", 10 | "white": "White" 11 | } 12 | -------------------------------------------------------------------------------- /composables/useNumberFormatter.js: -------------------------------------------------------------------------------- 1 | import numeral from 'numeral' 2 | 3 | export function useNumberFormatter() { 4 | return { 5 | toDollar: (value) => numeral(value).format('$0,0'), 6 | toK: (value) => numeral(value).format('$0a'), 7 | toPercent: (value) => numeral(value).format('0%'), 8 | toNumber: (value) => numeral(value).format('0,0'), 9 | } 10 | } -------------------------------------------------------------------------------- /pages/test.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | -------------------------------------------------------------------------------- /public/school-icons/four.svg: -------------------------------------------------------------------------------- 1 | 2 | four 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /assets/images/double-caret.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /components/documentation/Card.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | -------------------------------------------------------------------------------- /public/school-icons/two.svg: -------------------------------------------------------------------------------- 1 | 2 | two 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /assets/data/special_designations.json: -------------------------------------------------------------------------------- 1 | { 2 | "women_only": "Women-Only", 3 | "men_only": "Men-Only", 4 | "aanipi": "Asian American and Native American Pacific Islander-Serving Institution", 5 | "annh": "Alaska Native and Native Hawaiian-Serving Institution", 6 | "hispanic": "Hispanic-Serving Institution", 7 | "historically_black": "Historically Black College and University", 8 | "nant": "Native American Non-Tribal Institution", 9 | "predominantly_black": "Predominantly Black Institution", 10 | "tribal": "Tribal College and University" 11 | } 12 | -------------------------------------------------------------------------------- /components/RecaptchaCheckbox.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | -------------------------------------------------------------------------------- /components/SimpleTooltip.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | -------------------------------------------------------------------------------- /composables/useVuetify.js: -------------------------------------------------------------------------------- 1 | import { useTheme, useDisplay } from 'vuetify' 2 | 3 | export function useVuetify() { 4 | const theme = useTheme() 5 | const breakpoints = useDisplay() 6 | 7 | const color = (colorName, alpha = 1) => { 8 | const hexColor = theme.current.value.colors[colorName] 9 | 10 | if (alpha === 1) { 11 | return hexColor 12 | } 13 | 14 | // Convert hex to rgba 15 | const r = parseInt(hexColor.slice(1, 3), 16) 16 | const g = parseInt(hexColor.slice(3, 5), 16) 17 | const b = parseInt(hexColor.slice(5, 7), 16) 18 | 19 | return `rgba(${r}, ${g}, ${b}, ${alpha})` 20 | } 21 | 22 | return { 23 | theme, 24 | color, 25 | breakpoints 26 | } 27 | } -------------------------------------------------------------------------------- /assets/images/home/compare.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /components/documentation/Help.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | -------------------------------------------------------------------------------- /error.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | -------------------------------------------------------------------------------- /components/layout/UsaLockIcon.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | -------------------------------------------------------------------------------- /public/school-icons/certificate.svg: -------------------------------------------------------------------------------- 1 | 2 | certificate 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /components/layout/UsaGovIcon.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | -------------------------------------------------------------------------------- /assets/images/icon-Location.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /components/layout/UsaFlag.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /stores/banners.js: -------------------------------------------------------------------------------- 1 | // stores/banner.js 2 | export const useBannerStore = defineStore('banner', { 3 | state: () => ({ 4 | isWebinarBannerVisible: true 5 | }), 6 | 7 | actions: { 8 | initializeBannerState() { 9 | // Check localStorage on initialization 10 | if (import.meta.client) { 11 | const stored = localStorage.getItem('webinarBannerHidden') 12 | if (stored === 'true') { 13 | this.isWebinarBannerVisible = false 14 | } 15 | } 16 | }, 17 | 18 | hideBanner() { 19 | this.isWebinarBannerVisible = false 20 | // Persist to localStorage 21 | if (import.meta.client) { 22 | localStorage.setItem('webinarBannerHidden', 'true') 23 | } 24 | }, 25 | 26 | showBanner() { 27 | this.isWebinarBannerVisible = true 28 | // Remove from localStorage 29 | if (import.meta.client) { 30 | localStorage.removeItem('webinarBannerHidden') 31 | } 32 | } 33 | } 34 | }) -------------------------------------------------------------------------------- /public/school-icons/private.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /public/school-icons/profit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /public/school-icons/public.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /components/school/AddToCompare.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 35 | -------------------------------------------------------------------------------- /composables/useScroll.js: -------------------------------------------------------------------------------- 1 | export function useScroll() { 2 | const fixedHeaderHeightOffset = 150; 3 | 4 | const scrollToAnchor = (anchorId, offset = fixedHeaderHeightOffset, behavior = "smooth") => { 5 | let id = anchorId.replace('#', ''); 6 | const anchor = document.querySelector(`#${id}`); 7 | if (anchor) { 8 | const elementPosition = anchor.getBoundingClientRect().top; 9 | const offsetPosition = elementPosition + window.pageYOffset - offset; 10 | 11 | window.scrollTo({ 12 | top: offsetPosition, 13 | behavior, 14 | }); 15 | } 16 | } 17 | 18 | const scrollToElement = (element, offset = fixedHeaderHeightOffset) => { 19 | if (element && element instanceof Element) { 20 | const elementPosition = element.getBoundingClientRect().top; 21 | const offsetPosition = elementPosition + window.pageYOffset - offset; 22 | 23 | window.scrollTo({ 24 | top: offsetPosition, 25 | behavior: "smooth" 26 | }); 27 | } 28 | } 29 | 30 | return { 31 | scrollToAnchor, 32 | scrollToElement, 33 | } 34 | } -------------------------------------------------------------------------------- /composables/useApi.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | export const useApi = () => { 4 | const config = useRuntimeConfig(); 5 | 6 | const apiInstance = axios.create({ 7 | baseURL: config.public.apiUrl 8 | }); 9 | 10 | const apiGet = async (uri, params = {}) => { 11 | try { 12 | const response = await apiInstance.get(uri, { 13 | params: { 14 | api_key: config.public.apiKey, 15 | ...params 16 | } 17 | }); 18 | return response.data; 19 | } catch (error) { 20 | console.error('API Get Error:', error, uri, params); 21 | throw error; 22 | } 23 | }; 24 | 25 | const apiGetAll = async (uri, paramArray) => { 26 | try { 27 | const promises = paramArray.map(params => apiGet(uri, params)); 28 | const results = await Promise.all(promises).then(values => { 29 | return values; 30 | }); 31 | 32 | return results; 33 | } catch (error) { 34 | console.error('API GetAll Error:', error); 35 | throw error; 36 | } 37 | }; 38 | 39 | return { 40 | apiGet, 41 | apiGetAll 42 | }; 43 | }; -------------------------------------------------------------------------------- /components/search/canned/Slider.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 40 | 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | The College Scorecard transition project away from the [Gridsome Project](https://github.com/rti-international/scorecard-website) 2 | 3 | The transition includes: 4 | + Vue2 to [Vue3](https://vuejs.org/) 5 | + Vuetify2 to [Vuetify3](https://vuetifyjs.com/en/introduction/why-vuetify/#what-is-vuetify3f) 6 | + Gridsome to [Nuxt3](https://nuxt.com/) 7 | + Options API to [Composition API](https://vuejs.org/guide/extras/composition-api-faq.html#why-composition-api) 8 | + Vuex to [Pinia](https://pinia.vuejs.org/) 9 | 10 | ## Setup 11 | Make sure to install the dependencies: 12 | ```bash 13 | npm install 14 | ``` 15 | 16 | Run the app locally: 17 | ```bash 18 | npm run dev 19 | ``` 20 | 21 | ## Preview Build 22 | Start the development server on `http://localhost:3000`: 23 | 24 | ```bash 25 | npm run build 26 | npm run preview 27 | ``` 28 | 29 | ## Deploy 30 | 31 | Deploy app to the dev server: 32 | ```bash 33 | npm run deploy:dev 34 | ``` 35 | 36 | Deploy app to the staging server: 37 | ```bash 38 | npm run deploy:staging 39 | ``` 40 | 41 | Deploy app to the production server: 42 | ```bash 43 | npm run deploy:prod 44 | ``` -------------------------------------------------------------------------------- /components/layout/WebinarCTA.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 29 | 30 | -------------------------------------------------------------------------------- /middleware/school-search.js: -------------------------------------------------------------------------------- 1 | export default defineNuxtRouteMiddleware((to, from) => { 2 | let query = to.query 3 | let params_modified = false 4 | 5 | if (query.state) { 6 | if (Array.isArray(query.state)) { 7 | query.state = query.state.join(',') 8 | params_modified = true 9 | } 10 | } 11 | 12 | if (query.cip4_degree) { 13 | if (!Array.isArray(query.cip4_degree)) { 14 | query.cip4_degree = query.cip4_degree.split(',') 15 | params_modified = true 16 | } 17 | } 18 | 19 | if (query.size) { 20 | if (!Array.isArray(query.size)) { 21 | query.size = query.size.split(',') 22 | params_modified = true 23 | } 24 | } 25 | 26 | if (query.control) { 27 | if (!Array.isArray(query.control)) { 28 | query.control = query.control.split(',') 29 | params_modified = true 30 | } 31 | } 32 | 33 | if (query.locale) { 34 | if (!Array.isArray(query.locale)) { 35 | query.locale = query.locale.split(',') 36 | params_modified = true 37 | } 38 | } 39 | 40 | if (params_modified) { 41 | return navigateTo({ 42 | path: to.path, 43 | query: query 44 | }, { replace: true }) 45 | } 46 | }) -------------------------------------------------------------------------------- /components/Map.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 33 | 34 | -------------------------------------------------------------------------------- /components/home/CompareIcon.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 24 | 25 | -------------------------------------------------------------------------------- /public/school-icons/city.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | 17 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /composables/useRecaptcha.js: -------------------------------------------------------------------------------- 1 | // composables/useRecaptcha.js 2 | import { ref, onMounted } from 'vue' 3 | import { useRuntimeConfig } from '#app' 4 | 5 | export const useRecaptcha = (size = 'normal') => { 6 | const config = useRuntimeConfig() 7 | const siteKey = config.public.recaptchaKey 8 | 9 | const recaptchaLoaded = ref(false) 10 | const recaptchaToken = ref(null) 11 | let onSuccessCallback = null 12 | 13 | const loadRecaptchaScript = () => { 14 | const script = document.createElement('script') 15 | script.src = 'https://www.google.com/recaptcha/api.js' 16 | script.async = true 17 | script.defer = true 18 | document.head.appendChild(script) 19 | 20 | script.onload = () => { 21 | recaptchaLoaded.value = true 22 | } 23 | } 24 | 25 | const onRecaptchaVerified = (token) => { 26 | recaptchaToken.value = token 27 | if (onSuccessCallback) { 28 | onSuccessCallback(token) 29 | } 30 | } 31 | 32 | const setOnSuccess = (callback) => { 33 | onSuccessCallback = callback 34 | } 35 | 36 | onMounted(() => { 37 | loadRecaptchaScript() 38 | window.onRecaptchaVerified = onRecaptchaVerified 39 | }) 40 | 41 | return { 42 | siteKey, 43 | recaptchaLoaded, 44 | recaptchaToken, 45 | setOnSuccess, 46 | size 47 | } 48 | } -------------------------------------------------------------------------------- /components/compare/FieldsOfStudy/NumberOfGraduates.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 39 | 40 | -------------------------------------------------------------------------------- /components/compare/TooltipHeader.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | -------------------------------------------------------------------------------- /public/school-icons/small.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 11 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /components/compare/FieldsOfStudy/Data/Block.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 43 | 44 | -------------------------------------------------------------------------------- /components/chart/VerticalBarMedian.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | -------------------------------------------------------------------------------- /components/home/Fafsa.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 39 | 40 | -------------------------------------------------------------------------------- /components/home/Veterans.vue: -------------------------------------------------------------------------------- 1 | 45 | 46 | 59 | 60 | -------------------------------------------------------------------------------- /components/compare/Schools/Data/Section.vue: -------------------------------------------------------------------------------- 1 | 38 | 39 | -------------------------------------------------------------------------------- /assets/images/icon-financial-aid-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /components/compare/Schools/Data/Block.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 48 | 49 | -------------------------------------------------------------------------------- /assets/images/icon-financial-aid.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /components/search/FieldAutocomplete.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 31 | 32 | 80 | -------------------------------------------------------------------------------- /public/school-icons/suburban.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 12 | 14 | 15 | 16 | 17 | 18 | 20 | 22 | 26 | 27 | -------------------------------------------------------------------------------- /assets/scss/_breakpoints.scss: -------------------------------------------------------------------------------- 1 | $grid-breakpoints: ( 2 | 'xs': 0, 3 | 'sm': 600px, 4 | 'md': 960px, 5 | 'lg': 1280px, 6 | 'xl': 1920px, 7 | ); 8 | 9 | .v-container { 10 | @media (min-width: map-get($grid-breakpoints, 'lg')) { 11 | max-width: 1185px; 12 | } 13 | 14 | @media (min-width: map-get($grid-breakpoints, 'xl')) { 15 | max-width: 1300px; 16 | } 17 | } 18 | 19 | .v-container.v-container--fluid { 20 | max-width: 100%; 21 | } 22 | 23 | @mixin xs { 24 | @media (max-width: map-get($grid-breakpoints, 'sm') - 1) { 25 | @content; 26 | } 27 | } 28 | 29 | @mixin sm { 30 | @media (min-width: map-get($grid-breakpoints, 'sm')) and (max-width: map-get($grid-breakpoints, 'md') - 1) { 31 | @content; 32 | } 33 | } 34 | 35 | @mixin smAndUp { 36 | @media (min-width: map-get($grid-breakpoints, 'sm')) { 37 | @content; 38 | } 39 | } 40 | 41 | @mixin smAndDown { 42 | @media (max-width: map-get($grid-breakpoints, 'md') - 1) { 43 | @content; 44 | } 45 | } 46 | 47 | @mixin md { 48 | @media (min-width: map-get($grid-breakpoints, 'md')) and (max-width: map-get($grid-breakpoints, 'lg') - 1) { 49 | @content; 50 | } 51 | } 52 | 53 | @mixin mdAndUp { 54 | @media (min-width: map-get($grid-breakpoints, 'md')) { 55 | @content; 56 | } 57 | } 58 | 59 | @mixin mdAndDown { 60 | @media (max-width: map-get($grid-breakpoints, 'lg') - 1) { 61 | @content; 62 | } 63 | } 64 | 65 | @mixin lg { 66 | @media (min-width: map-get($grid-breakpoints, 'lg')) and (max-width: map-get($grid-breakpoints, 'xl') - 1) { 67 | @content; 68 | } 69 | } 70 | 71 | @mixin lgAndUp { 72 | @media (min-width: map-get($grid-breakpoints, 'lg')) { 73 | @content; 74 | } 75 | } 76 | 77 | @mixin lgAndDown { 78 | @media (max-width: map-get($grid-breakpoints, 'xl') - 1) { 79 | @content; 80 | } 81 | } 82 | 83 | @mixin xl { 84 | @media (min-width: map-get($grid-breakpoints, 'xl')) { 85 | @content; 86 | } 87 | } 88 | 89 | @mixin pxAndUp($px) { 90 | @media (min-width: $px) { 91 | @content; 92 | } 93 | } 94 | 95 | @mixin pxAndDown($px) { 96 | @media (max-width: $px - 1) { 97 | @content; 98 | } 99 | } -------------------------------------------------------------------------------- /assets/images/icon-pathways.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /assets/images/icon-pathways-blue.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /public/school-icons/town.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 10 | 12 | 13 | 14 | 18 | 22 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /pages/data/glossary.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /assets/images/icon-Note.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /components/chart/Donut.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | -------------------------------------------------------------------------------- /composables/useSiteData.js: -------------------------------------------------------------------------------- 1 | import { ref, computed } from 'vue' 2 | import cip_2_digit from "~/assets/data/cip_2_digit.json" 3 | import cip_4_digit from "~/assets/data/cip_4_digit.json" 4 | import glossary from "~/assets/data/glossary.json" 5 | import race_ethnicity from "~/assets/data/race_ethnicity.json" 6 | import religious_affiliations from "~/assets/data/religious_affiliations.json" 7 | import special_designations from "~/assets/data/special_designations.json" 8 | import states from "~/assets/data/states.json" 9 | import cip_6_digit from "~/assets/data/cip_6_digit_2020.json" 10 | import repayment_rates from "~/assets/data/repayment_rates.json" 11 | 12 | export function useSiteData() { 13 | const site = ref({ 14 | data: { 15 | cip_2_digit, 16 | cip_4_digit, 17 | cip_6_digit, 18 | glossary, 19 | race_ethnicity, 20 | religious_affiliations, 21 | special_designations, 22 | states, 23 | repayment_rates, 24 | } 25 | }) 26 | 27 | const RELIGIOUS_AFFILIATIONS_BY_NUMBER = computed(() => { 28 | return site.value.data.religious_affiliations.reduce((object, value) => { 29 | object[value.value] = value.title 30 | return object 31 | }, {}) 32 | }) 33 | 34 | const CIP2 = computed(() => 35 | site.value.data.cip_2_digit.reduce((object, value) => { 36 | object[value.label] = value.value 37 | return object 38 | }, {}) 39 | ) 40 | 41 | const CIP4 = computed(() => 42 | site.value.data.cip_4_digit.map(value => ({ 43 | cip4: value.label, 44 | field: value.value.replace('.', '') 45 | })) 46 | ) 47 | 48 | function locateCip4Field(cip4Code) { 49 | let formattedCip4Code = cip4Code.toString() 50 | 51 | let cip4Object = CIP4.value.find((cip4Object) => 52 | cip4Object.cip4.replace(/\./g, '') === formattedCip4Code.replace(/\./g, '') 53 | ) 54 | 55 | return cip4Object && cip4Object.field ? cip4Object.field : null 56 | } 57 | 58 | function findAllCip6fromCip4(cip4Code) { 59 | return site.value.data.cip_6_digit.filter((cip6) => 60 | Number(cip6.code.slice(0, 4)) === Number(cip4Code) 61 | ) 62 | } 63 | 64 | return { 65 | site, 66 | RELIGIOUS_AFFILIATIONS_BY_NUMBER, 67 | CIP2, 68 | CIP4, 69 | locateCip4Field, 70 | findAllCip6fromCip4 71 | } 72 | } -------------------------------------------------------------------------------- /components/layout/DataNavigation.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 48 | 49 | -------------------------------------------------------------------------------- /components/compare/FieldsOfStudy/Data/Section.vue: -------------------------------------------------------------------------------- 1 | 52 | 53 | -------------------------------------------------------------------------------- /assets/images/icon-google-drive.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/data/states.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"value":"AL","title":"Alabama"}, 3 | {"value":"AK","title":"Alaska"}, 4 | {"value":"AS","title":"American Samoa"}, 5 | {"value":"AZ","title":"Arizona"}, 6 | {"value":"AR","title":"Arkansas"}, 7 | {"value":"CA","title":"California"}, 8 | {"value":"CO","title":"Colorado"}, 9 | {"value":"CT","title":"Connecticut"}, 10 | {"value":"DE","title":"Delaware"}, 11 | {"value":"DC","title":"District of Columbia"}, 12 | {"value":"FM","title":"Federated States of Micronesia"}, 13 | {"value":"FL","title":"Florida"}, 14 | {"value":"GA","title":"Georgia"}, 15 | {"value":"GU","title":"Guam"}, 16 | {"value":"HI","title":"Hawaii"}, 17 | {"value":"ID","title":"Idaho"}, 18 | {"value":"IL","title":"Illinois"}, 19 | {"value":"IN","title":"Indiana"}, 20 | {"value":"IA","title":"Iowa"}, 21 | {"value":"KS","title":"Kansas"}, 22 | {"value":"KY","title":"Kentucky"}, 23 | {"value":"LA","title":"Louisiana"}, 24 | {"value":"ME","title":"Maine"}, 25 | {"value":"MD","title":"Maryland"}, 26 | {"value":"MA","title":"Massachusetts"}, 27 | {"value":"MH","title":"Marshall Islands"}, 28 | {"value":"MI","title":"Michigan"}, 29 | {"value":"MN","title":"Minnesota"}, 30 | {"value":"MS","title":"Mississippi"}, 31 | {"value":"MO","title":"Missouri"}, 32 | {"value":"MT","title":"Montana"}, 33 | {"value":"NE","title":"Nebraska"}, 34 | {"value":"NV","title":"Nevada"}, 35 | {"value":"NH","title":"New Hampshire"}, 36 | {"value":"NJ","title":"New Jersey"}, 37 | {"value":"NM","title":"New Mexico"}, 38 | {"value":"NY","title":"New York"}, 39 | {"value":"NC","title":"North Carolina"}, 40 | {"value":"ND","title":"North Dakota"}, 41 | {"value":"MP","title":"Northern Mariana Islands"}, 42 | {"value":"OH","title":"Ohio"}, 43 | {"value":"OK","title":"Oklahoma"}, 44 | {"value":"OR","title":"Oregon"}, 45 | {"value":"PW","title":"Palau"}, 46 | {"value":"PA","title":"Pennsylvania"}, 47 | {"value":"PR","title":"Puerto Rico"}, 48 | {"value":"RI","title":"Rhode Island"}, 49 | {"value":"SC","title":"South Carolina"}, 50 | {"value":"SD","title":"South Dakota"}, 51 | {"value":"TN","title":"Tennessee"}, 52 | {"value":"TX","title":"Texas"}, 53 | {"value":"UT","title":"Utah"}, 54 | {"value":"VT","title":"Vermont"}, 55 | {"value":"VI","title":"Virgin Islands"}, 56 | {"value":"VA","title":"Virginia"}, 57 | {"value":"WA","title":"Washington"}, 58 | {"value":"WV","title":"West Virginia"}, 59 | {"value":"WI","title":"Wisconsin"}, 60 | {"value":"WY","title":"Wyoming"} 61 | ] 62 | -------------------------------------------------------------------------------- /components/compare/FieldsOfStudy/SalaryAfterCompleting.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 56 | 75 | 76 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt-app", 3 | "private": true, 4 | "type": "module", 5 | "scripts": { 6 | "dev": "npx nuxi dev --dotenv .env.development --port 3000", 7 | "build": "npx nuxi generate --dotenv .env.development", 8 | "build:prod": "DEV=false npx nuxi generate --dotenv .env.production", 9 | "preview": "npx serve .output/public", 10 | "deploy:dev-branch": "DEV=true BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD) && BUILD=development npx nuxi generate --dotenv .env.development && aws --profile scorecard s3 sync .output/public s3://scorecard-development-9d7y2giuzkhar2vn94xb/$BRANCH_NAME --exclude '*.DS_Store' && aws --profile scorecard cloudfront create-invalidation --distribution-id E2PKIP6XK74A9G --paths '/*'", 11 | "deploy:dev": "DEV=true && npx nuxi generate --dotenv .env.development && aws --profile scorecard s3 sync .output/public s3://scorecard-development-9d7y2giuzkhar2vn94xb --exclude '*.DS_Store' && aws --profile scorecard cloudfront create-invalidation --distribution-id E2PKIP6XK74A9G --paths '/*'", 12 | "deploy:staging": "DEV=false npx nuxi generate --dotenv .env.staging && aws --profile scorecard s3 sync .output/public s3://scorecard-staging-9d7y2giuzkhar2vn94xb --exclude '*.DS_Store' && aws --profile scorecard cloudfront create-invalidation --distribution-id E2C2BK6W1PBAKO --paths '/*'", 13 | "deploy:prod": "DEV=false npx nuxi generate --dotenv .env.production && aws --profile scorecard s3 sync .output/public s3://scorecard-production-9d7y2giuzkhar2vn94xb --exclude '*.DS_Store' && aws --profile scorecard cloudfront create-invalidation --distribution-id E1EWCM0BUNA8YO --paths '/*'" 14 | }, 15 | "dependencies": { 16 | "@fortawesome/fontawesome-free": "^6.6.0", 17 | "@mdi/font": "^7.4.47", 18 | "@nuxt/image": "^1.8.0", 19 | "@nuxtjs/leaflet": "^1.2.6", 20 | "@pinia/nuxt": "^0.5.4", 21 | "axios": "^1.7.7", 22 | "chart.js": "^4.4.4", 23 | "focus-trap": "^7.6.2", 24 | "focus-trap-vue": "^4.0.3", 25 | "google-charts": "^2.0.0", 26 | "numeral": "^2.0.6", 27 | "nuxt": "^3.15.4", 28 | "nuxt-gtag": "^3.0.1", 29 | "vue": "latest", 30 | "vue-chartjs": "^5.3.1", 31 | "vue-numeral-filter": "^2.2.0", 32 | "vue-router": "latest", 33 | "vue-uswds": "^1.9.0" 34 | }, 35 | "devDependencies": { 36 | "nuxt-lodash": "^2.5.3", 37 | "sass": "^1.79.3", 38 | "sass-loader": "^16.0.2", 39 | "vite-plugin-vuetify": "^2.0.4", 40 | "vuetify": "^3.7.2" 41 | }, 42 | "overrides": { 43 | "vue": "latest" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /components/school/panel/FieldOfStudyToggle.vue: -------------------------------------------------------------------------------- 1 | 30 | 31 | 77 | 78 | -------------------------------------------------------------------------------- /components/chart/Ratio.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 38 | 39 | -------------------------------------------------------------------------------- /components/home/Arrow.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 75 | 76 | -------------------------------------------------------------------------------- /components/Toggle.vue: -------------------------------------------------------------------------------- 1 | 38 | 39 | 82 | 83 | -------------------------------------------------------------------------------- /public/school-icons/medium.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 11 | 14 | 17 | 20 | 23 | 26 | 29 | 30 | -------------------------------------------------------------------------------- /components/home/Resources.vue: -------------------------------------------------------------------------------- 1 | 71 | 72 | 81 | 82 | -------------------------------------------------------------------------------- /pages/data/index.vue: -------------------------------------------------------------------------------- 1 | 66 | 67 | 72 | -------------------------------------------------------------------------------- /components/layout/UsaBanner.vue: -------------------------------------------------------------------------------- 1 | 48 | 49 | 56 | 57 | -------------------------------------------------------------------------------- /assets/images/icon-docs.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /assets/images/icon-pdf.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /assets/images/icon-ppt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /components/layout/SearchNavigation.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 68 | 69 | -------------------------------------------------------------------------------- /assets/images/icon-slides.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /public/school-icons/large.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 10 | 13 | 16 | 19 | 22 | 25 | 27 | 29 | 31 | 33 | 34 | -------------------------------------------------------------------------------- /assets/images/Pathway-Icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /assets/images/icon-pathways-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /assets/images/icon-doc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /assets/data/cip_2_digit.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"label":"01","value":"AGRICULTURAL/ANIMAL/PLANT/VETERINARY SCIENCE AND RELATED FIELDS."}, 3 | {"label":"03","value":"NATURAL RESOURCES AND CONSERVATION."}, 4 | {"label":"04","value":"ARCHITECTURE AND RELATED SERVICES."}, 5 | {"label":"05","value":"AREA, ETHNIC, CULTURAL, GENDER, AND GROUP STUDIES."}, 6 | {"label":"09","value":"COMMUNICATION, JOURNALISM, AND RELATED PROGRAMS."}, 7 | {"label":"10","value":"COMMUNICATIONS TECHNOLOGIES/TECHNICIANS AND SUPPORT SERVICES."}, 8 | {"label":"11","value":"COMPUTER AND INFORMATION SCIENCES AND SUPPORT SERVICES."}, 9 | {"label":"12","value":"CULINARY, ENTERTAINMENT, AND PERSONAL SERVICES."}, 10 | {"label":"13","value":"EDUCATION."}, 11 | {"label":"14","value":"ENGINEERING."}, 12 | {"label":"15","value":"ENGINEERING/ENGINEERING-RELATED TECHNOLOGIES/TECHNICIANS."}, 13 | {"label":"16","value":"FOREIGN LANGUAGES, LITERATURES, AND LINGUISTICS."}, 14 | {"label":"19","value":"FAMILY AND CONSUMER SCIENCES/HUMAN SCIENCES."}, 15 | {"label":"22","value":"LEGAL PROFESSIONS AND STUDIES."}, 16 | {"label":"23","value":"ENGLISH LANGUAGE AND LITERATURE/LETTERS."}, 17 | {"label":"24","value":"LIBERAL ARTS AND SCIENCES, GENERAL STUDIES AND HUMANITIES."}, 18 | {"label":"25","value":"LIBRARY SCIENCE."}, 19 | {"label":"26","value":"BIOLOGICAL AND BIOMEDICAL SCIENCES."}, 20 | {"label":"27","value":"MATHEMATICS AND STATISTICS."}, 21 | {"label":"28","value":"MILITARY SCIENCE, LEADERSHIP AND OPERATIONAL ART."}, 22 | {"label":"29","value":"MILITARY TECHNOLOGIES AND APPLIED SCIENCES."}, 23 | {"label":"30","value":"MULTI/INTERDISCIPLINARY STUDIES."}, 24 | {"label":"31","value":"PARKS, RECREATION, LEISURE, FITNESS, AND KINESIOLOGY."}, 25 | {"label":"32","value":"BASIC SKILLS AND DEVELOPMENTAL/REMEDIAL EDUCATION."}, 26 | {"label":"33","value":"CITIZENSHIP ACTIVITIES."}, 27 | {"label":"34","value":"HEALTH-RELATED KNOWLEDGE AND SKILLS."}, 28 | {"label":"35","value":"INTERPERSONAL AND SOCIAL SKILLS."}, 29 | {"label":"36","value":"LEISURE AND RECREATIONAL ACTIVITIES."}, 30 | {"label":"37","value":"PERSONAL AWARENESS AND SELF-IMPROVEMENT."}, 31 | {"label":"38","value":"PHILOSOPHY AND RELIGIOUS STUDIES."}, 32 | {"label":"39","value":"THEOLOGY AND RELIGIOUS VOCATIONS."}, 33 | {"label":"40","value":"PHYSICAL SCIENCES."}, 34 | {"label":"41","value":"SCIENCE TECHNOLOGIES/TECHNICIANS."}, 35 | {"label":"42","value":"PSYCHOLOGY."}, 36 | {"label":"43","value":"HOMELAND SECURITY, LAW ENFORCEMENT, FIREFIGHTING AND RELATED PROTECTIVE SERVICES."}, 37 | {"label":"44","value":"PUBLIC ADMINISTRATION AND SOCIAL SERVICE PROFESSIONS."}, 38 | {"label":"45","value":"SOCIAL SCIENCES."}, 39 | {"label":"46","value":"CONSTRUCTION TRADES."}, 40 | {"label":"47","value":"MECHANIC AND REPAIR TECHNOLOGIES/TECHNICIANS."}, 41 | {"label":"48","value":"PRECISION PRODUCTION."}, 42 | {"label":"49","value":"TRANSPORTATION AND MATERIALS MOVING."}, 43 | {"label":"50","value":"VISUAL AND PERFORMING ARTS."}, 44 | {"label":"51","value":"HEALTH PROFESSIONS AND RELATED PROGRAMS."}, 45 | {"label":"52","value":"BUSINESS, MANAGEMENT, MARKETING, AND RELATED SUPPORT SERVICES."}, 46 | {"label":"53","value":"HIGH SCHOOL/SECONDARY DIPLOMAS AND CERTIFICATES."}, 47 | {"label":"54","value":"HISTORY."}, 48 | {"label":"60","value":"HEALTH PROFESSIONS RESIDENCY/FELLOWSHIP PROGRAMS."}, 49 | {"label":"61","value":"MEDICAL RESIDENCY/FELLOWSHIP PROGRAMS."} 50 | ] 51 | -------------------------------------------------------------------------------- /stores/analytics.js: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { useRuntimeConfig } from '#app' 3 | 4 | function initializeGtag() { 5 | if (import.meta.client) { 6 | const { gtag, initialize } = useGtag() 7 | try { 8 | initialize() 9 | return gtag 10 | } catch (e) { 11 | console.error('[gtag] error', e) 12 | return null 13 | } 14 | } 15 | } 16 | 17 | export const useAnalytics = defineStore('analytics', { 18 | state: () => ({ 19 | gtag: initializeGtag(), 20 | }), 21 | 22 | getters: { 23 | // get 24 | }, 25 | 26 | actions: { 27 | GATrackEvent(category, action, label = '', customParams = {}) { 28 | try { 29 | if (import.meta.client && this.gtag) { 30 | const config = useRuntimeConfig() 31 | if (config.public.isLocalBuild || config.public.isDevBuild) { 32 | return console.info(`[gtag] event - Category: ${category}, Action: ${action}, Label: ${label || window.location.pathname}, Build: ${config.public.isStagingBuild ? 'Staging' : 'Dev'}`); 33 | } 34 | 35 | this.gtag('event', action, { 36 | event_category: category, 37 | event_label: label || window.location.pathname, 38 | ...customParams, 39 | }) 40 | } 41 | } catch (e) { 42 | console.error('[gtag] event error', e) 43 | } 44 | }, 45 | 46 | trackAccordion(accordion) { 47 | this.GATrackEvent('[Data] Expand Accordion', accordion) 48 | }, 49 | 50 | transitionOutboundLink(event) { 51 | let href = '(unknown)' 52 | if (!event.target.href) { 53 | href = event.target.parentNode.href 54 | } else if (event.target.className.match(/v-btn__content/)) { 55 | href = event.target.parentNode.href 56 | } else { 57 | href = event.target.href 58 | } 59 | 60 | if (href.includes('.gov')) { 61 | this.GATrackEvent('External Link', href) 62 | } else if (confirm("You are leaving the College Scorecard. \n\nThe U.S. Department of Education does not necessarily endorse the views expressed or the data and facts presented on this external site. \n\nLinks are provided by the institutions and are only updated about once a year. As such, over the course of the year, some links may break or websites may be taken offline.")) { 63 | this.GATrackEvent('External Link', href) 64 | } else { 65 | event.preventDefault() 66 | } 67 | }, 68 | 69 | trackDownload(file) { 70 | this.GATrackEvent('Downloads', file) 71 | }, 72 | 73 | trackShare(network) { 74 | this.GATrackEvent('Social Share', network) 75 | }, 76 | 77 | trackOutcome(combo) { 78 | this.GATrackEvent('Outcome', 'Toggle', combo) 79 | }, 80 | 81 | trackCompareList(list) { 82 | this.GATrackEvent('Comparison', 'School IDs', list) 83 | }, 84 | 85 | trackNavigation(path) { 86 | this.GATrackEvent('Internal Link', path) 87 | }, 88 | 89 | trackMultipleStates(states) { 90 | this.GATrackEvent('Multiple States', states) 91 | }, 92 | 93 | trackSearchFilters(filterParams) { 94 | if (!filterParams || Object.keys(filterParams).length === 0) { 95 | return 96 | } 97 | 98 | this.GATrackEvent('Search Filters', 'Filter Applied', '', filterParams) 99 | } 100 | }, 101 | }) 102 | -------------------------------------------------------------------------------- /stores/compare.js: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { useLocalStorage } from '@vueuse/core' 3 | 4 | export const useCompareStore = defineStore('compare', { 5 | state: () => ({ 6 | fos: useLocalStorage('fos', []), 7 | institutions: useLocalStorage('institutions', []), 8 | drawerOpen: useLocalStorage('drawerOpen', false), 9 | clearForm: false, 10 | outboundUrl: null, 11 | highlightedFos: null, 12 | highlightedInstitution: null, 13 | 14 | temporaryFos: null, 15 | temporaryInstitutions: null, 16 | }), 17 | 18 | getters: { 19 | getInstitutions: (state) => state.institutions, 20 | getFieldsOfStudy: (state) => state.fos, 21 | }, 22 | 23 | actions: { 24 | schoolParams(obj) { 25 | return { 26 | id: obj.id, 27 | school: { name: obj.school ? obj.school.name : obj['school.name'] }, 28 | } 29 | }, 30 | 31 | addSchool(obj) { 32 | this.institutions = this.institutions || [] 33 | 34 | if (this.institutions.length < 10) { 35 | this.institutions.push(this.schoolParams(obj)) 36 | } 37 | }, 38 | 39 | toggleSchool(obj) { 40 | this.institutions = this.institutions || [] 41 | const index = this.institutions.findIndex(inst => inst.id === obj.id) 42 | if (index !== -1) { 43 | this.institutions.splice(index, 1) 44 | } else { 45 | this.addSchool(obj) 46 | } 47 | }, 48 | 49 | removeSchool(obj) { 50 | const index = this.institutions.findIndex(inst => inst.id === obj.id) 51 | if (index !== -1) { 52 | this.institutions.splice(index, 1) 53 | } 54 | }, 55 | 56 | fieldOfStudyParams(obj) { 57 | return { 58 | code: obj.code, 59 | unit_id: obj.unit_id, 60 | credential: { level: obj.credential.level, title: obj.credential.title }, 61 | school: { name: obj.school.name }, 62 | title: obj.title, 63 | } 64 | }, 65 | 66 | addFieldOfStudy(obj) { 67 | this.fos = this.fos || [] 68 | 69 | if (this.fos.length < 10) { 70 | this.fos.push(this.fieldOfStudyParams(obj)) 71 | } 72 | }, 73 | 74 | toggleFieldOfStudy(obj) { 75 | const index = this.fos.findIndex(fos => ( 76 | fos.code === obj.code && 77 | fos.unit_id === obj.unit_id && 78 | fos.credential.level === obj.credential.level 79 | )) 80 | 81 | if (index !== -1) { 82 | this.fos.splice(index, 1) 83 | } else { 84 | this.addFieldOfStudy(obj) 85 | } 86 | }, 87 | 88 | findFieldOfStudy(obj) { 89 | return this.fos.find(fos => ( 90 | fos.code === obj.code && 91 | fos.unit_id === obj.unit_id && 92 | fos.credential.level === obj.credential.level 93 | )) 94 | }, 95 | 96 | removeFieldOfStudy(obj) { 97 | const index = this.fos.findIndex(fos => ( 98 | fos.code === obj.code && 99 | fos.unit_id === obj.unit_id && 100 | fos.credential.level === obj.credential.level 101 | )) 102 | 103 | if (index !== -1) { 104 | this.fos.splice(index, 1) 105 | } 106 | }, 107 | 108 | toggleDrawer(value = null) { 109 | if (value != null) { 110 | this.drawerOpen = value 111 | } else { 112 | this.drawerOpen = !this.drawerOpen 113 | } 114 | }, 115 | 116 | clearForm() { 117 | this.fos = [] 118 | this.institutions = [] 119 | }, 120 | 121 | setOutboundUrl(value = null) { 122 | this.outboundUrl = value 123 | } 124 | }, 125 | }) -------------------------------------------------------------------------------- /pages/data/data-documentation.vue: -------------------------------------------------------------------------------- 1 | 94 | 95 | 99 | -------------------------------------------------------------------------------- /components/compare/Schools/TypicalEarnings.vue: -------------------------------------------------------------------------------- 1 | 80 | 81 | 98 | 99 | -------------------------------------------------------------------------------- /composables/useLocationCheck.js: -------------------------------------------------------------------------------- 1 | import { reactive } from 'vue' 2 | import { useRouter } from 'vue-router' 3 | 4 | export function useLocationCheck() { 5 | const router = useRouter() 6 | 7 | const location = reactive({ 8 | latLon: null, 9 | miles: 50, // In Miles. 10 | isLoading: false, 11 | error: null 12 | }) 13 | 14 | function handleLocationCheck(redirect = "") { 15 | location.isLoading = true 16 | location.error = null 17 | 18 | if (navigator.geolocation) { 19 | navigator.geolocation.getCurrentPosition( 20 | (position) => { 21 | location.latLon = calculateBoundingBox( 22 | position.coords.latitude, 23 | position.coords.longitude, 24 | location.miles * 1.609 // Convert miles to KM (Approximate) 25 | ) 26 | location.isLoading = false 27 | if (redirect !== "") { 28 | const lat = `${location.latLon.min_lat.toFixed(4)}..${location.latLon.max_lat.toFixed(4)}` 29 | const long = `${location.latLon.min_lon.toFixed(4)}..${location.latLon.max_lon.toFixed(4)}` 30 | // Uncomment the following line if you want to add lat and long to the redirect URL 31 | // redirect += `&lat=${lat}&long=${long}` 32 | router.push(redirect) 33 | } 34 | }, 35 | (error) => { 36 | location.error = "Not Available" 37 | location.isLoading = false 38 | if (redirect !== "") { 39 | router.push(redirect) 40 | } 41 | }, 42 | { 43 | timeout: 15000, 44 | enableHighAccuracy: true, 45 | maximumAge: 0, 46 | } 47 | ) 48 | } else { 49 | location.isLoading = false 50 | location.error = "Not Available" 51 | if (redirect !== "") { 52 | router.push(redirect) 53 | } 54 | } 55 | } 56 | 57 | function calculateBoundingBox(lat, long, distance) { 58 | if (distance < 0) { 59 | return 'Illegal arguments' 60 | } 61 | 62 | // helper functions (degrees<->radians) 63 | const degToRad = (deg) => deg * (Math.PI / 180) 64 | const radToDeg = (rad) => (180 * rad) / Math.PI 65 | 66 | // coordinate limits 67 | const MIN_LAT = degToRad(-90) 68 | const MAX_LAT = degToRad(90) 69 | const MIN_LON = degToRad(-180) 70 | const MAX_LON = degToRad(180) 71 | 72 | // Earth's radius (km) 73 | const R = 6378.1 74 | 75 | // angular distance in radians on a great circle 76 | const radDist = distance / R 77 | 78 | // center point coordinates (rad) 79 | const radLat = degToRad(lat) 80 | const radLon = degToRad(long) 81 | 82 | // minimum and maximum latitudes for given distance 83 | let minLat = radLat - radDist 84 | let maxLat = radLat + radDist 85 | 86 | // minimum and maximum longitudes for given distance 87 | let minLon, maxLon 88 | 89 | // define deltaLon to help determine min and max longitudes 90 | const deltaLon = Math.asin(Math.sin(radDist) / Math.cos(radLat)) 91 | 92 | if (minLat > MIN_LAT && maxLat < MAX_LAT) { 93 | minLon = radLon - deltaLon 94 | maxLon = radLon + deltaLon 95 | if (minLon < MIN_LON) minLon += 2 * Math.PI 96 | if (maxLon > MAX_LON) maxLon -= 2 * Math.PI 97 | } else { 98 | // a pole is within the given distance 99 | minLat = Math.max(minLat, MIN_LAT) 100 | maxLat = Math.min(maxLat, MAX_LAT) 101 | minLon = MIN_LON 102 | maxLon = MAX_LON 103 | } 104 | 105 | return { 106 | min_lat: radToDeg(minLat), 107 | max_lat: radToDeg(maxLat), 108 | min_lon: radToDeg(minLon), 109 | max_lon: radToDeg(maxLon) 110 | } 111 | } 112 | 113 | return { 114 | location, 115 | handleLocationCheck 116 | } 117 | } -------------------------------------------------------------------------------- /components/search/canned/Container.vue: -------------------------------------------------------------------------------- 1 | 65 | 66 | -------------------------------------------------------------------------------- /components/school/OutcomesConfig.vue: -------------------------------------------------------------------------------- 1 | 81 | 82 | -------------------------------------------------------------------------------- /plugins/vuetify.ts: -------------------------------------------------------------------------------- 1 | import { createVuetify } from 'vuetify' 2 | import * as components from 'vuetify/components' 3 | import * as directives from 'vuetify/directives' 4 | import { fa } from 'vuetify/iconsets/fa' 5 | import { aliases, mdi } from 'vuetify/iconsets/mdi' 6 | 7 | export default defineNuxtPlugin((nuxtApp) => { 8 | const vuetify = createVuetify({ 9 | components, 10 | directives, 11 | icons: { 12 | defaultSet: 'mdi', 13 | aliases, 14 | sets: { 15 | fa, 16 | mdi, 17 | }, 18 | }, 19 | theme: { 20 | defaultTheme: 'light', 21 | themes: { 22 | light: { 23 | dark: false, 24 | colors: { 25 | // colors derived from stylesheet: https://xd.adobe.com/view/2e1e489a-996e-4c73-b885-629da889b966-7b4d/specs/ 26 | // i made up the error color as it's not in the design system 27 | 'white': '#FFFFFF', 28 | 'black': '#000000', 29 | 'error': '#E5484D', 30 | 31 | 'primary-blue': '#10274E', 32 | 'primary-aqua': '#026AA2', 33 | 'primary-green': '#007000', // this isn't part of the stylesheet, but it's used everywhere so... 34 | 'primary-yellow': '#FDB022', 35 | 36 | 'secondary-green': '#027A48', 37 | 'secondary-blue': '#1570EF', 38 | 'secondary-gray': '#EAEEF5', 39 | 'secondary-yellow': '#FEF0C7', 40 | 41 | 'tertiary-green': '#7BD88C', 42 | 'tertiary-yellow': '#FFFAEB', 43 | 44 | 'blue-900': '#10274E', 45 | 'blue-800': '#194185', 46 | 'blue-700': '#175CD3', 47 | 'blue-600': '#1570EF', 48 | 'blue-500': '#2E90FA', 49 | 'blue-400': '#53B1FD', 50 | 'blue-300': '#84CAFF', 51 | 'blue-200': '#B2DDFF', 52 | 'blue-100': '#D1E9FF', 53 | 'blue-50': '#EFF8FF', 54 | 'blue-25': '#F5FAFF', 55 | 56 | 'aqua-900': '#0B4A6F', 57 | 'aqua-800': '#065986', 58 | 'aqua-700': '#026AA2', 59 | 'aqua-600': '#0086C9', 60 | 'aqua-500': '#0BA5EC', 61 | 'aqua-400': '#36BFFA', 62 | 'aqua-300': '#7CD4FD', 63 | 'aqua-200': '#B9E6FE', 64 | 'aqua-100': '#E0F2FE', 65 | 'aqua-50': '#F0F9FF', 66 | 'aqua-25': '#F5FBFF', 67 | 68 | 'green-900': '#054F31', 69 | 'green-800': '#05603A', 70 | 'green-700': '#027A48', 71 | 'green-600': '#17A067', 72 | 'green-500': '#44BA89', 73 | 'green-400': '#47CE95', 74 | 'green-300': '#7BD88C', 75 | 'green-200': '#A6F4C5', 76 | 'green-100': '#D1FADF', 77 | 'green-50': '#ECFDF3', 78 | 'green-25': '#F6FEF9', 79 | 80 | 'yellow-950': '#db9525', 81 | 'yellow-900': '#FDB022', 82 | 'yellow-800': '#FEC84B', 83 | 'yellow-700': '#FEDF89', 84 | 'yellow-600': '#FEF0C7', 85 | 'yellow-500': '#FFFAEB', 86 | 'yellow-400': '#FFFCF5', 87 | 88 | 'gray-900': '#292E34', 89 | 'gray-800': '#484E55', 90 | 'gray-700': '#636363', 91 | 'gray-600': '#889099', 92 | 'gray-500': '#A8B0BA', 93 | 'gray-400': '#C3C9D3', 94 | 'gray-300': '#D6DCE5', 95 | 'gray-200': '#DFE6F0', 96 | 'gray-100': '#EAEEF5', 97 | 'gray-50': '#F2F5FA', 98 | 'gray-25': '#FAFCFF', 99 | }, 100 | variables: { 101 | 'medium-emphasis-opacity': 1, 102 | 'input-control-height': '30px', 103 | } 104 | }, 105 | }, 106 | }, 107 | }) 108 | 109 | nuxtApp.vueApp.use(vuetify) 110 | }) -------------------------------------------------------------------------------- /components/layout/FooterCTA.vue: -------------------------------------------------------------------------------- 1 | 89 | 90 | 93 | 94 | -------------------------------------------------------------------------------- /nuxt.config.ts: -------------------------------------------------------------------------------- 1 | // https://nuxt.com/docs/api/configuration/nuxt-config 2 | import vuetify, { transformAssetUrls } from 'vite-plugin-vuetify' 3 | 4 | const isLocalBuild = process.env.NODE_ENV === 'development' 5 | const isDevBuild = process.env.NODE_ENV === 'production' && (process.env.DEV === 'true') 6 | 7 | export default defineNuxtConfig({ 8 | ssr: true, 9 | compatibilityDate: '2024-04-03', 10 | devtools: { enabled: true }, 11 | 12 | runtimeConfig: { 13 | public: { 14 | version: '3.5.3', 15 | apiKey: process.env.SCORECARD_API_KEY, 16 | apiUrl: process.env.SCORECARD_API_URL, 17 | recaptchaKey: process.env.RECAPTCHA_KEY, 18 | apiSignupKey: process.env.API_SIGNUP_KEY, 19 | isLocalBuild: isLocalBuild, 20 | isDevBuild: isDevBuild, 21 | baseURL: process.env.NUXT_BASE_URL 22 | } 23 | }, 24 | 25 | ignore: [ 26 | "**/*.stories.{js,cts,mts,ts,jsx,tsx}", 27 | "**/*.{spec,test}.{js,cts,mts,ts,jsx,tsx}", 28 | "**/*.d.{cts,mts,ts}", 29 | "**/.{pnpm-store,vercel,netlify,output,git,cache,data}", 30 | ".nuxt/analyze", 31 | ".nuxt", 32 | "**/-*.*", 33 | 34 | // Dev-only test page 35 | isDevBuild ? "" : "**/test.*", 36 | ].filter(Boolean), 37 | 38 | build: { 39 | transpile: ['vuetify', 'leaflet', '@vue-leaflet/vue-leaflet'], 40 | }, 41 | 42 | modules: [ 43 | '@pinia/nuxt', 44 | 'nuxt-lodash', 45 | '@nuxtjs/leaflet', 46 | 'nuxt-gtag', 47 | (_options, nuxt) => { 48 | nuxt.hooks.hook('vite:extendConfig', (config) => { 49 | // @ts-expect-error 50 | config.plugins.push(vuetify({ autoImport: true })) 51 | }) 52 | }, 53 | ], 54 | 55 | gtag: { 56 | enabled: process.env.NODE_ENV === 'production', 57 | id: 'G-19BFKPWV7B', 58 | }, 59 | 60 | css: [ 61 | 'vuetify/styles', 62 | '@mdi/font/css/materialdesignicons.css', 63 | '@fortawesome/fontawesome-free/css/fontawesome.min.css', 64 | '@fortawesome/fontawesome-free/css/solid.min.css', 65 | '@fortawesome/fontawesome-free/css/regular.min.css', 66 | "~/assets/scss/_fonts.scss" 67 | ], 68 | 69 | vite: { 70 | vue: { 71 | template: { 72 | transformAssetUrls, 73 | }, 74 | }, 75 | css: { 76 | preprocessorOptions: { 77 | scss: { 78 | additionalData: ` 79 | @use "~/assets/scss/_breakpoints.scss" as *; 80 | @import "@/assets/scss/_functions.scss"; 81 | `, 82 | silenceDeprecations: ['legacy-js-api'], 83 | }, 84 | }, 85 | }, 86 | }, 87 | 88 | app: { 89 | baseURL: process.env.BRANCH_NAME ? `/${process.env.BRANCH_NAME}/` : '/', 90 | head: { 91 | meta: [ 92 | { charset: 'utf-8' }, 93 | { name: 'viewport', content: 'width=device-width, initial-scale=1' }, 94 | { 'http-equiv': "Cache-control", content: "private, no-store" }, 95 | { name: 'HandheldFriendly', property: 'HandheldFriendly', content: 'True' }, 96 | { name: 'MobileOptimized', property: 'MobileOptimized', content: '320' }, 97 | { name: "google-site-verification", property: 'google-site-verification', content: "joZQgj-M8GQ05V29ojfVsbsNk44SRgGqJfws9tBcnPU" }, 98 | { name: "google-site-verification", property: 'google-site-verification', content: "V-KEdRwSWd6GSLEWRBddZy6B5yLCs6vkRRflrImQiKE" }, 99 | ], 100 | link: [ 101 | { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }, 102 | { 103 | rel: 'stylesheet', 104 | href: 'https://use.typekit.net/nmj8tls.css' 105 | }, 106 | { 107 | rel: 'icon', 108 | type: 'image/png', 109 | href: '/favicon.png' 110 | } 111 | ], 112 | script: [ 113 | { id: "_fed_an_ua_tag", src: "https://dap.digitalgov.gov/Universal-Federated-Analytics-Min.js" }, 114 | { type: "text/javascript", src: "https://www.googletagmanager.com/gtag/js?id=UA-48605964-29", async: true }, 115 | { type: "text/javascript", src: "https://www.googletagmanager.com/gtag/js?id=UA-48605964-29", async: true }, 116 | ], 117 | }, 118 | }, 119 | }) -------------------------------------------------------------------------------- /assets/images/icon-Financial-Aid-training.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /components/compare/FieldsOfStudy/FinancialAid.vue: -------------------------------------------------------------------------------- 1 | 94 | 95 | 118 | 119 | -------------------------------------------------------------------------------- /assets/images/icon-guide.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /assets/scss/style.scss: -------------------------------------------------------------------------------- 1 | // unfortunately scss functions are breaking on build, so I have to dupe css here 2 | // todo: fix scss functions on build 3 | $gray-100: #EAEEF5; 4 | $gray-200: #DFE6F0; 5 | $gray-400: #C3C9D3; 6 | $gray-700: #6C737C; 7 | $primary-green: #007000; 8 | $primary-blue: #10274E; 9 | $secondary-blue: #1570EF; 10 | 11 | $base-font-family: "Inter", Helvetica, arial, sans-serif; 12 | $header-font-family: neue-haas-grotesk-display, Helvetica, arial, sans-serif; 13 | 14 | .text-h1, 15 | .text-h2, 16 | .text-h3, 17 | .text-h4, 18 | .text-h5, 19 | .text-h6, 20 | .text-subtitle-1, 21 | .text-subtitle-2, 22 | .text-body-1, 23 | .text-body-2, 24 | .text-button, 25 | .text-caption, 26 | .text-overline 27 | { 28 | font-family: $base-font-family !important; 29 | } 30 | 31 | .title, 32 | .display-1, 33 | .display-2, 34 | .display-3, 35 | .display-4, 36 | .display-5, 37 | .display-6, 38 | .display-7, 39 | .subtitle-1, 40 | .subtitle-2 { 41 | font-family: $header-font-family !important; 42 | } 43 | 44 | .display-2 { 45 | font-size: 28px !important; 46 | line-height: 32px !important; 47 | } 48 | 49 | .display-3 { 50 | font-size: 3rem !important; 51 | line-height: 32px !important; 52 | } 53 | 54 | .display-5 { 55 | font-size: 50px; 56 | line-height: 59.65px; 57 | font-weight: 500; 58 | } 59 | 60 | .display-6 { 61 | font-size: 40px; 62 | line-height: 47.72px; 63 | font-weight: 400; 64 | } 65 | 66 | .display-7 { 67 | font-size: 28px; 68 | font-weight: 500; 69 | line-height: 33.4px; 70 | } 71 | 72 | .font-header { 73 | font-family: $header-font-family; 74 | } 75 | 76 | .font-base { 77 | font-family: $base-font-family; 78 | } 79 | 80 | .v-application { 81 | // VUETIFY OVERRIDES 82 | .v-selection-control__wrapper { 83 | color: #636363; 84 | } 85 | 86 | .v-label { 87 | color: black !important; 88 | } 89 | 90 | input::placeholder { 91 | color: use-theme('gray-700') !important; 92 | opacity: 1; 93 | } 94 | 95 | .v-label { 96 | color: use-theme('gray-700'); 97 | opacity: 1; 98 | } 99 | 100 | 101 | .v-btn { 102 | letter-spacing: normal; 103 | text-transform: none; 104 | box-shadow: none; 105 | } 106 | 107 | .v-pagination { 108 | button { 109 | box-shadow: 0px 1px 1px #0000001a !important; 110 | border: 1px solid $gray-100; 111 | height: auto; 112 | padding: 1px 4px; 113 | } 114 | } 115 | 116 | .v-expansion-panel-title { 117 | font-weight: 500; 118 | font-family: $header-font-family !important; 119 | font-size: 18px; 120 | line-height: 140%; 121 | } 122 | 123 | .v-card { 124 | overflow-wrap: normal; 125 | border: 1px solid $gray-200; 126 | border-radius: 6px; 127 | } 128 | 129 | .v-chip__close { 130 | color: $primary-green !important; 131 | } 132 | 133 | 134 | // GENERAL OVERRIDES 135 | font-family: $base-font-family !important; 136 | background-color: $gray-100 !important; 137 | 138 | h1, h2, h3, h4, h5, h6 { 139 | font-family: $header-font-family !important; 140 | line-height: 125% !important; 141 | } 142 | 143 | body, a { 144 | color: $primary-green; 145 | } 146 | 147 | hr { 148 | border: 1px solid $gray-200; 149 | border-bottom-style: none; 150 | margin-top: 1rem; 151 | margin-bottom: 1rem; 152 | } 153 | 154 | footer { 155 | a { 156 | color: white !important; 157 | } 158 | } 159 | 160 | .overline { 161 | font-size: 12px !important; 162 | line-height: 160% !important; 163 | letter-spacing: normal !important; 164 | } 165 | 166 | .sr-only { 167 | display: none; 168 | } 169 | 170 | .hover-tip { 171 | max-width: 270px; 172 | } 173 | 174 | .navy-text { 175 | color: $primary-blue; 176 | } 177 | 178 | .medium-light-blue-text { 179 | color: $secondary-blue; 180 | } 181 | 182 | .data-na { 183 | padding: 0.5rem; 184 | border: 1px dashed $gray-400; 185 | color: $gray-700; 186 | text-align: center; 187 | margin: 0.8rem 0; 188 | } 189 | 190 | .mini-data-na { 191 | padding: 0.5rem; 192 | color: $gray-700; 193 | font-size: 0.85rem; 194 | border: 1px dashed $gray-400; 195 | } 196 | 197 | a.close-filter { 198 | color: $gray-700 !important; 199 | font-size:14px; 200 | 201 | &:active, &:hover { 202 | color: $gray-700; 203 | } 204 | } 205 | 206 | .search-label { 207 | font-weight:600; 208 | font-size:14px; 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /components/compare/Schools/Costs.vue: -------------------------------------------------------------------------------- 1 | 91 | 92 | 126 | 127 | -------------------------------------------------------------------------------- /components/layout/Subnav.vue: -------------------------------------------------------------------------------- 1 | 67 | 68 | 109 | 110 | --------------------------------------------------------------------------------