From 636b8b0a9f58f4e5d80f6ed9fa6c364a2d06ca55 Mon Sep 17 00:00:00 2001 From: Rami Abdou Date: Wed, 27 Mar 2024 09:49:10 -0700 Subject: [PATCH] copy all files --- .eslintrc.js | 4 + .github/CODEOWNERS | 1 + .github/ISSUE_TEMPLATE/bug_report.md | 32 + .github/ISSUE_TEMPLATE/config.yml | 4 + .github/ISSUE_TEMPLATE/feature_request.md | 19 + .github/pull_request_template.md | 23 + .github/workflows/ci.yml | 75 + .gitignore | 36 + .prettierrc.js | 8 + .vscode/settings.json | 22 + CODE_OF_CONDUCT.md | 132 + CONTRIBUTING.md | 195 + LICENSE.md | 20 + README.md | 109 +- apps/admin-dashboard/.env.example | 14 + apps/admin-dashboard/.eslintrc.js | 4 + apps/admin-dashboard/app/entry.client.tsx | 29 + apps/admin-dashboard/app/entry.server.tsx | 168 + apps/admin-dashboard/app/root.tsx | 85 + .../app/routes/_dashboard._index.tsx | 10 + .../app/routes/_dashboard.admins.add.tsx | 162 + .../_dashboard.applications.$id._index.tsx | 360 + .../_dashboard.applications.$id.email.tsx | 148 + .../routes/_dashboard.applications.$id.tsx | 34 + .../app/routes/_dashboard.applications.tsx | 256 + .../routes/_dashboard.bull.$queue._index.tsx | 15 + .../_dashboard.bull.$queue.jobs.$id.tsx | 235 + .../_dashboard.bull.$queue.jobs.add.tsx | 160 + .../routes/_dashboard.bull.$queue.jobs.tsx | 261 + ..._dashboard.bull.$queue.repeatables.add.tsx | 154 + .../_dashboard.bull.$queue.repeatables.tsx | 191 + .../app/routes/_dashboard.bull.$queue.tsx | 83 + .../app/routes/_dashboard.bull._index.tsx | 12 + .../app/routes/_dashboard.bull.tsx | 48 + .../routes/_dashboard.events.$id.import.tsx | 217 + .../app/routes/_dashboard.events.create.tsx | 199 + .../app/routes/_dashboard.events.tsx | 222 + ...rd.gamification.activities.$id.archive.tsx | 105 + ...board.gamification.activities.$id.edit.tsx | 165 + ..._dashboard.gamification.activities.add.tsx | 131 + .../_dashboard.gamification.activities.tsx | 176 + .../app/routes/_dashboard.icebreakers.add.tsx | 113 + .../app/routes/_dashboard.logout.tsx | 28 + ....onboarding-sessions.$id.add-attendees.tsx | 130 + .../routes/_dashboard.onboarding-sessions.tsx | 224 + .../_dashboard.onboarding-sessions.upload.tsx | 135 + .../app/routes/_dashboard.programs.create.tsx | 150 + .../routes/_dashboard.resources.create.tsx | 128 + .../app/routes/_dashboard.schools.create.tsx | 167 + .../app/routes/_dashboard.schools.tsx | 227 + .../_dashboard.students.$id.activate.tsx | 112 + .../routes/_dashboard.students.$id.email.tsx | 150 + .../_dashboard.students.$id.points.grant.tsx | 169 + .../routes/_dashboard.students.$id.remove.tsx | 108 + .../_dashboard.students.import.programs.tsx | 256 + .../_dashboard.students.import.resources.tsx | 275 + ...dashboard.students.import.scholarships.tsx | 240 + .../app/routes/_dashboard.students.tsx | 285 + .../routes/_dashboard.surveys.$id.import.tsx | 160 + .../app/routes/_dashboard.surveys.create.tsx | 156 + .../app/routes/_dashboard.surveys.tsx | 208 + .../admin-dashboard/app/routes/_dashboard.tsx | 113 + apps/admin-dashboard/app/routes/health.tsx | 5 + .../app/routes/login._index.tsx | 52 + .../app/routes/login.oauth.tsx | 51 + .../app/routes/login.otp.send.tsx | 72 + .../app/routes/login.otp.verify.tsx | 107 + apps/admin-dashboard/app/routes/login.tsx | 28 + .../app/routes/members.search.tsx | 44 + .../app/shared/components/activity-form.tsx | 116 + .../app/shared/components/card.tsx | 33 + .../components/onboarding-session-form.tsx | 83 + .../app/shared/constants.server.ts | 31 + apps/admin-dashboard/app/shared/constants.ts | 76 + .../app/shared/cookies.server.ts | 14 + .../admin-dashboard/app/shared/core.server.ts | 1 + apps/admin-dashboard/app/shared/core.ui.ts | 1 + .../app/shared/queries/admin.ts | 16 + .../app/shared/queries/student.ts | 8 + .../app/shared/session.server.ts | 92 + apps/admin-dashboard/app/tailwind.css | 18 + apps/admin-dashboard/env.d.ts | 2 + apps/admin-dashboard/global.d.ts | 12 + apps/admin-dashboard/package.json | 49 + apps/admin-dashboard/postcss.config.mjs | 5 + apps/admin-dashboard/public/favicon.ico | Bin 0 -> 167043 bytes .../public/images/colorstack-background.png | Bin 0 -> 5146 bytes .../public/images/colorstack-wordmark.png | Bin 0 -> 143322 bytes .../public/images/linkedin.png | Bin 0 -> 5823 bytes apps/admin-dashboard/railway.json | 21 + apps/admin-dashboard/tailwind.config.js | 16 + apps/admin-dashboard/tsconfig.json | 12 + apps/admin-dashboard/vite.config.ts | 11 + apps/api/.env.example | 37 + apps/api/.eslintrc.js | 5 + apps/api/package.json | 33 + apps/api/railway.json | 21 + apps/api/src/main.ts | 105 + apps/api/src/routers/health.router.ts | 7 + apps/api/src/routers/oauth.router.ts | 90 + apps/api/src/routers/slack-event.router.ts | 178 + apps/api/src/routers/slack-event.types.ts | 154 + apps/api/src/shared/env.ts | 83 + apps/api/src/shared/types.ts | 3 + apps/api/tsconfig.json | 10 + apps/member-profile/.env.example | 22 + apps/member-profile/.eslintrc.js | 4 + apps/member-profile/app/entry.client.tsx | 36 + apps/member-profile/app/entry.server.tsx | 166 + apps/member-profile/app/root.tsx | 91 + apps/member-profile/app/routes/_index.tsx | 7 + .../app/routes/_profile.directory._index.tsx | 23 + .../app/routes/_profile.directory.join.1.tsx | 162 + .../app/routes/_profile.directory.join.2.tsx | 141 + .../app/routes/_profile.directory.join.3.tsx | 152 + .../app/routes/_profile.directory.join.4.tsx | 235 + .../routes/_profile.directory.join._index.tsx | 35 + .../routes/_profile.directory.join.finish.tsx | 49 + .../app/routes/_profile.directory.join.tsx | 145 + .../app/routes/_profile.directory.tsx | 547 + .../app/routes/_profile.directory_.$id.tsx | 460 + .../app/routes/_profile.events._index.tsx | 10 + .../_profile.events.past.$id.attendees.tsx | 118 + .../app/routes/_profile.events.past.tsx | 174 + .../app/routes/_profile.events.tsx | 68 + .../_profile.events.upcoming.$id.register.tsx | 176 + ...file.events.upcoming.$id.registrations.tsx | 101 + .../app/routes/_profile.events.upcoming.tsx | 252 + .../_profile.home.claim-swag-pack._index.tsx | 188 + ...file.home.claim-swag-pack.confirmation.tsx | 27 + .../routes/_profile.home.claim-swag-pack.tsx | 29 + .../app/routes/_profile.home.tsx | 788 ++ .../app/routes/_profile.logout.tsx | 28 + .../app/routes/_profile.points.tsx | 679 + .../app/routes/_profile.profile._index.tsx | 7 + .../_profile.profile.education.$id.delete.tsx | 123 + .../_profile.profile.education.$id.edit.tsx | 258 + .../routes/_profile.profile.education.add.tsx | 163 + .../app/routes/_profile.profile.education.tsx | 101 + .../_profile.profile.emails.add.finish.tsx | 208 + .../_profile.profile.emails.add.start.tsx | 186 + ..._profile.profile.emails.change-primary.tsx | 184 + .../app/routes/_profile.profile.emails.tsx | 109 + .../app/routes/_profile.profile.general.tsx | 200 + .../routes/_profile.profile.icebreakers.tsx | 252 + .../app/routes/_profile.profile.personal.tsx | 216 + .../app/routes/_profile.profile.socials.tsx | 172 + .../app/routes/_profile.profile.tsx | 178 + .../_profile.profile.work.$id.delete.tsx | 111 + .../routes/_profile.profile.work.$id.edit.tsx | 264 + .../app/routes/_profile.profile.work.add.tsx | 170 + .../app/routes/_profile.profile.work.tsx | 114 + apps/member-profile/app/routes/_profile.tsx | 63 + .../app/routes/_public.apply._index.tsx | 215 + .../app/routes/_public.apply.thank-you.tsx | 24 + .../app/routes/_public.apply.tsx | 23 + .../app/routes/_public.claim-swag-pack.tsx | 7 + .../app/routes/_public.login._index.tsx | 59 + .../app/routes/_public.login.oauth.tsx | 56 + .../app/routes/_public.login.otp.send.tsx | 72 + .../app/routes/_public.login.otp.verify.tsx | 112 + .../app/routes/_public.login.tsx | 52 + apps/member-profile/app/routes/_public.tsx | 11 + apps/member-profile/app/routes/cities.$id.tsx | 16 + .../app/routes/cities.autocomplete.tsx | 27 + apps/member-profile/app/routes/companies.tsx | 40 + .../app/routes/countries.search.tsx | 56 + apps/member-profile/app/routes/health.tsx | 5 + apps/member-profile/app/routes/schools.tsx | 49 + .../app/shared/components/card.tsx | 33 + .../app/shared/components/city-combobox.tsx | 89 + .../shared/components/company-combobox.tsx | 72 + .../components/education-experience.tsx | 74 + .../app/shared/components/education-form.tsx | 207 + .../app/shared/components/empty-state.tsx | 31 + .../shared/components/ethnicity-combobox.tsx | 122 + .../app/shared/components/event.tsx | 86 + .../app/shared/components/profile.general.tsx | 65 + .../shared/components/profile.icebreakers.tsx | 66 + .../shared/components/profile.personal.tsx | 120 + .../app/shared/components/profile.tsx | 44 + .../app/shared/constants.server.ts | 47 + apps/member-profile/app/shared/constants.ts | 55 + .../app/shared/cookies.server.ts | 22 + apps/member-profile/app/shared/core.server.ts | 1 + apps/member-profile/app/shared/core.ui.ts | 1 + .../app/shared/mixpanel.server.ts | 118 + .../app/shared/queries/index.ts | 210 + .../app/shared/session.server.ts | 70 + apps/member-profile/app/shared/url.utils.ts | 14 + .../app/shared/utils/format.utils.ts | 27 + apps/member-profile/app/tailwind.css | 18 + apps/member-profile/env.d.ts | 2 + apps/member-profile/global.d.ts | 12 + apps/member-profile/package.json | 52 + apps/member-profile/postcss.config.mjs | 5 + .../public/apple-touch-icon.png | Bin 0 -> 1865 bytes apps/member-profile/public/favicon.ico | Bin 0 -> 15406 bytes .../member-profile/public/images/calendly.svg | 1 + .../public/images/colorstack-background.png | Bin 0 -> 5146 bytes .../images/colorstack-notebook-navy.png | Bin 0 -> 4675 bytes .../images/colorstack-shirt-black-1.png | Bin 0 -> 10003 bytes .../images/colorstack-shirt-black-2.png | Bin 0 -> 4685 bytes .../public/images/colorstack-wordmark.png | Bin 0 -> 143322 bytes apps/member-profile/public/images/github.svg | 1 + .../public/images/instagram.svg | 5 + .../member-profile/public/images/linkedin.png | Bin 0 -> 5823 bytes .../public/images/member-profile-home.png | Bin 0 -> 316470 bytes apps/member-profile/public/images/slack.svg | 22 + .../public/images/university.png | Bin 0 -> 567 bytes apps/member-profile/public/images/x.png | Bin 0 -> 102327 bytes apps/member-profile/railway.json | 22 + apps/member-profile/tailwind.config.js | 22 + apps/member-profile/tsconfig.json | 12 + apps/member-profile/vite.config.ts | 11 + config/eslint/base.js | 9 + config/eslint/package.json | 13 + config/tsconfig/base.json | 19 + config/tsconfig/package.json | 6 + config/tsconfig/react-library.json | 11 + config/tsconfig/remix.json | 15 + docs/how-to-enable-integrations.md | 180 + docs/how-to-implement-a-database-migration.md | 63 + package.json | 29 + packages/core-ui/package.json | 41 + packages/core-ui/rollup.config.js | 30 + packages/core-ui/src/css/_breakpoints.scss | 30 + packages/core-ui/src/css/shared.css | 81 + .../core-ui/src/hooks/use-delayed-value.ts | 31 + packages/core-ui/src/hooks/use-hydrated.ts | 21 + .../core-ui/src/hooks/use-on-click-outside.ts | 41 + .../core-ui/src/hooks/use-search-params.ts | 12 + packages/core-ui/src/index.ts | 43 + packages/core-ui/src/ui/address.tsx | 106 + packages/core-ui/src/ui/button.tsx | 123 + .../src/ui/checkbox/checkbox.module.scss | 14 + packages/core-ui/src/ui/checkbox/checkbox.tsx | 85 + packages/core-ui/src/ui/combobox-popover.tsx | 119 + packages/core-ui/src/ui/combobox.tsx | 142 + packages/core-ui/src/ui/date-picker.tsx | 27 + packages/core-ui/src/ui/divider.tsx | 3 + .../src/ui/dropdown/dropdown.module.scss | 18 + packages/core-ui/src/ui/dropdown/dropdown.tsx | 77 + packages/core-ui/src/ui/form.tsx | 177 + packages/core-ui/src/ui/icon-button.tsx | 84 + packages/core-ui/src/ui/input.tsx | 49 + packages/core-ui/src/ui/link.tsx | 14 + .../core-ui/src/ui/modal/modal.module.scss | 71 + packages/core-ui/src/ui/modal/modal.tsx | 86 + packages/core-ui/src/ui/multi-combobox.tsx | 171 + packages/core-ui/src/ui/pagination.tsx | 232 + packages/core-ui/src/ui/pill.tsx | 63 + .../core-ui/src/ui/radio/radio.module.scss | 13 + packages/core-ui/src/ui/radio/radio.tsx | 83 + packages/core-ui/src/ui/search-bar.tsx | 27 + .../core-ui/src/ui/select/select.module.scss | 13 + packages/core-ui/src/ui/select/select.tsx | 50 + packages/core-ui/src/ui/spinner.tsx | 27 + packages/core-ui/src/ui/table.tsx | 207 + packages/core-ui/src/ui/text.tsx | 57 + packages/core-ui/src/ui/textarea.tsx | 31 + .../core-ui/src/ui/toast/toast.module.scss | 51 + packages/core-ui/src/ui/toast/toast.tsx | 85 + packages/core-ui/src/utils/constants.ts | 84 + packages/core-ui/src/utils/cx.ts | 20 + packages/core-ui/src/utils/zod.ts | 64 + packages/core-ui/tsconfig.json | 5 + packages/core-ui/types.d.ts | 18 + packages/core/.env.example | 5 + packages/core/package.json | 63 + packages/core/src/admin-dashboard.server.ts | 28 + packages/core/src/admin-dashboard.ui.ts | 16 + packages/core/src/api.ts | 33 + packages/core/src/infrastructure/bull/bull.ts | 27 + .../src/infrastructure/bull/bull.types.ts | 583 + .../src/infrastructure/bull/use-cases/job.ts | 90 + .../bull/use-cases/register-worker.ts | 67 + .../core/src/infrastructure/database/index.ts | 3 + .../migrations/2024-01-29T17:23:16Z-init.ts | 1821 +++ .../2024-01-29T19:05:29Z-birthdate.ts | 12 + .../2024-02-12T21:28:42Z-fix-removal.ts | 93 + .../2024-03-11T10:33:01Z-job_offers.ts | 36 + ...4-03-18T17:06:13Z-birthday-notification.ts | 15 + .../2024-03-18T19:45:26Z-birthday-default.ts | 39 + .../database/scripts/migrate.ts | 16 + .../infrastructure/database/scripts/seed.ts | 169 + .../shared/create-database-connection.ts | 26 + .../infrastructure/database/shared/migrate.ts | 60 + .../database/vitest-environment-kysely.ts | 36 + packages/core/src/infrastructure/redis.ts | 79 + packages/core/src/member-profile.server.ts | 40 + packages/core/src/member-profile.ui.ts | 36 + .../get-active-streak-leaderboard-position.ts | 84 + .../queries/get-active-streak-leaderboard.ts | 69 + .../queries/get-active-streak.ts | 42 + .../shared/active-status.shared.ts | 13 + .../use-cases/backfill-active-statuses.ts | 85 + .../use-cases/create-new-active-statuses.ts | 69 + .../core/src/modules/admin/admin.types.ts | 24 + .../src/modules/admin/use-cases/add-admin.ts | 36 + .../src/modules/airtable/airtable.shared.ts | 55 + .../src/modules/airtable/airtable.worker.ts | 29 + .../create-airtable-member-record.ts | 82 + .../use-cases/create-airtable-record.ts | 31 + .../use-cases/delete-airtable-record.ts | 39 + .../use-cases/update-airtable-record.ts | 43 + .../modules/application/application.worker.ts | 29 + .../events/application-accepted.ts | 24 + .../application/events/application-created.ts | 21 + .../events/application-rejected.ts | 37 + .../queries/count-pending-applications.ts | 15 + .../application/queries/get-application.ts | 25 + .../application/queries/list-applications.ts | 76 + .../application/ui/application-form.tsx | 554 + .../modules/application/ui/major-combobox.tsx | 86 + .../application/ui/school-combobox.tsx | 86 + .../use-cases/accept-application.ts | 95 + .../modules/application/use-cases/apply.ts | 59 + .../use-cases/reject-application.ts | 23 + .../use-cases/review-application.ts | 101 + .../use-cases/update-application-email.ts | 28 + .../authentication/authentication.types.ts | 55 + .../modules/authentication/oauth.service.ts | 42 + .../authentication/one-time-code.worker.ts | 17 + .../services/google-oauth.service.ts | 38 + .../services/slack-oauth.service.ts | 33 + .../authentication/shared/oauth.utils.ts | 70 + .../authentication/ui/one-time-code-form.tsx | 35 + .../use-cases/expire-one-time-code.ts | 8 + .../use-cases/login-with-oauth.ts | 62 + .../use-cases/send-one-time-code.ts | 81 + .../use-cases/verify-one-time-code.ts | 41 + .../src/modules/education/education.types.ts | 98 + .../src/modules/education/education.worker.ts | 21 + .../education/events/education-added.ts | 12 + .../education/events/education-deleted.ts | 12 + .../education/use-cases/add-education.ts | 32 + .../use-cases/check-most-recent-education.ts | 47 + .../education/use-cases/create-school.ts | 22 + .../education/use-cases/delete-education.ts | 21 + .../education/use-cases/edit-education.ts | 45 + .../modules/employment/employment.types.ts | 105 + .../modules/employment/employment.worker.ts | 21 + .../events/work-experience-added.ts | 12 + .../events/work-experience-deleted.ts | 12 + .../queries/get-crunchbase-organization.ts | 100 + .../employment/queries/get-work-experience.ts | 38 + .../queries/list-work-experiences.ts | 43 + .../search-crunchbase-organizations.ts | 95 + .../employment/shared/crunchbase.utils.ts | 33 + .../modules/employment/ui/work-experience.tsx | 66 + .../src/modules/employment/ui/work-form.tsx | 354 + .../use-cases/add-work-experience.ts | 55 + .../use-cases/delete-work-experience.ts | 25 + .../use-cases/edit-work-experience.ts | 45 + .../save-company-if-necessary.test.ts | 67 + .../use-cases/save-company-if-necessary.ts | 58 + .../modules/event/airmeet-event.service.ts | 314 + .../core/src/modules/event/event.worker.ts | 33 + .../modules/event/events/event-attended.ts | 18 + .../modules/event/events/event-registered.ts | 47 + .../event/queries/count-past-events.ts | 16 + .../event/queries/count-upcoming-events.ts | 16 + .../src/modules/event/queries/get-event.ts | 39 + .../queries/get-events-attended-count.ts | 13 + .../src/modules/event/queries/list-events.ts | 36 + .../modules/event/use-cases/create-event.ts | 33 + .../event/use-cases/register-for-event.ts | 27 + .../event/use-cases/sync-airmeet-event.ts | 74 + .../use-cases/sync-recent-airmeet-events.ts | 20 + .../feature-flag/feature-flag.shared.ts | 25 + .../queries/is-feature-flag-enabled.ts | 31 + .../initialize-feature-flag-server.ts | 26 + .../gamification/gamification.worker.ts | 21 + .../gamification/queries/get-total-points.ts | 23 + .../use-cases/archive-activity.ts | 9 + .../gamification/use-cases/edit-activity.ts | 29 + .../use-cases/grant-gamification-points.ts | 205 + .../use-cases/revoke-gamification-points.ts | 109 + .../modules/icebreaker/icebreaker.types.ts | 29 + .../queries/get-icebreaker-prompts.ts | 17 + .../queries/get-icebreaker-responses.ts | 24 + .../use-cases/add-icebreaker-prompt.ts | 14 + .../use-cases/upsert-icebreaker-responses.ts | 15 + .../src/modules/location/location.shared.ts | 24 + .../src/modules/location/location.types.ts | 14 + .../queries/get-autocompleted-cities.ts | 63 + .../location/queries/get-city-details.ts | 65 + .../mailchimp/email-marketing.shared.ts | 37 + .../mailchimp/email-marketing.worker.ts | 52 + .../events/mailchimp-campaign-opened.ts | 11 + .../modules/mailchimp/mailchimp.types.d.ts | 146 + .../use-cases/add-mailchimp-list-member.ts | 50 + .../use-cases/remove-mailchimp-list-member.ts | 31 + .../use-cases/sync-mailchimp-campaign.ts | 373 + .../use-cases/sync-mailchimp-list.ts | 132 + .../use-cases/update-mailchimp-list-member.ts | 39 + .../events/activation-step-completed.ts | 263 + .../modules/member/events/member-activated.ts | 28 + .../modules/member/events/member-created.ts | 50 + .../member/events/member-email-added.ts | 12 + .../events/member-primary-email-changed.ts | 96 + .../modules/member/events/member-removed.ts | 32 + .../src/modules/member/member-email.worker.ts | 21 + .../core/src/modules/member/member.worker.ts | 52 + .../core/src/modules/member/profile.worker.ts | 17 + .../member/queries/find-member-by-email.ts | 8 + .../member/use-cases/activate-member.ts | 14 + .../use-cases/backfill-engagement-records.ts | 214 + .../member/use-cases/join-member-directory.ts | 23 + .../use-cases/send-birthday-notification.ts | 36 + .../send-profile-views-notification.ts | 46 + .../member/use-cases/update-member-email.ts | 58 + .../member/use-cases/view-member-profile.ts | 18 + .../notification/notification.worker.ts | 21 + .../notification/shared/email.utils.ts | 15 + .../notification/use-cases/send-email.ts | 146 + .../use-cases/send-slack-notification.ts | 29 + .../events/onboarding-session-attended.ts | 57 + .../onboarding-session.types.ts | 19 + .../onboarding-session.worker.ts | 17 + .../add-onboarding-session-attendees.ts | 51 + .../use-cases/upload-onboarding-session.ts | 54 + .../modules/sentry/use-cases/report-error.ts | 21 + .../slack/events/slack-message-added.ts | 21 + .../events/slack-profile-picture-changed.ts | 35 + .../slack/events/slack-workspace-joined.ts | 32 + .../core/src/modules/slack/instances/index.ts | 7 + .../slack/queries/count-messages-sent.ts | 13 + .../slack/services/slack-admin.service.ts | 136 + .../slack/services/slack-channel.service.ts | 25 + .../slack/services/slack-message.service.ts | 69 + .../slack/services/slack-user.service.ts | 37 + .../core/src/modules/slack/slack.types.ts | 50 + .../core/src/modules/slack/slack.worker.ts | 73 + .../slack/use-cases/add-slack-message.ts | 104 + .../slack/use-cases/add-slack-reaction.ts | 94 + .../slack/use-cases/archive-slack-channel.ts | 13 + .../slack/use-cases/change-slack-message.ts | 16 + .../slack/use-cases/create-slack-channel.ts | 22 + .../slack/use-cases/deactivate-slack-user.ts | 8 + .../slack/use-cases/delete-slack-channel.ts | 8 + .../slack/use-cases/delete-slack-message.ts | 35 + .../use-cases/invite-to-slack-workspace.ts | 8 + .../slack/use-cases/remove-slack-reaction.ts | 35 + .../slack/use-cases/rename-slack-channel.ts | 13 + .../use-cases/unarchive-slack-channel.ts | 13 + .../modules/survey/events/survey.responded.ts | 13 + .../core/src/modules/survey/survey.types.ts | 38 + .../core/src/modules/survey/survey.worker.ts | 17 + .../modules/survey/use-cases/create-survey.ts | 20 + .../use-cases/import-survey-responses.ts | 84 + .../modules/swag-pack/swag-pack.service.ts | 271 + .../src/modules/swag-pack/swag-pack.types.ts | 14 + .../src/modules/swag-pack/swag-pack.worker.ts | 17 + .../swag-pack/use-cases/claim-swag-pack.ts | 65 + .../use-cases/notify-swag-pack-inventory.ts | 22 + packages/core/src/shared/constants.ts | 8 + packages/core/src/shared/env.ts | 41 + packages/core/src/shared/errors.ts | 50 + packages/core/src/shared/types.ts | 23 + packages/core/src/shared/utils/auth.utils.ts | 29 + packages/core/src/shared/utils/core.utils.ts | 45 + packages/core/src/shared/utils/csv.utils.ts | 22 + packages/core/src/shared/utils/ip.utils.ts | 66 + .../core/src/shared/utils/rate-limiter.ts | 100 + packages/core/src/shared/utils/test.utils.ts | 41 + packages/core/src/shared/utils/zod.utils.ts | 64 + packages/core/tsconfig.json | 13 + packages/core/tsup.config.ts | 12 + packages/core/vitest.config.ts | 26 + .../emails/application-accepted.tsx | 82 + .../emails/application-created.tsx | 46 + .../emails/application-rejected.tsx | 37 + .../emails/components/email.tsx | 203 + .../emails/one-time-code-sent.tsx | 31 + .../emails/primary-email-changed.tsx | 55 + .../emails/student-activated.tsx | 61 + .../emails/student-attended-onboarding.tsx | 78 + .../emails/student-removed.tsx | 31 + packages/email-templates/package.json | 28 + packages/email-templates/src/index.ts | 9 + packages/email-templates/src/types.ts | 72 + packages/email-templates/tsconfig.json | 7 + packages/feature-ui/package.json | 26 + packages/feature-ui/src/index.ts | 4 + packages/feature-ui/src/ui/dashboard.tsx | 218 + packages/feature-ui/src/ui/login.tsx | 139 + .../feature-ui/src/ui/profile-picture.tsx | 48 + packages/feature-ui/src/ui/public.tsx | 39 + packages/feature-ui/tsconfig.json | 5 + packages/types/package.json | 12 + packages/types/src/domain/application.ts | 63 + packages/types/src/domain/email-marketing.ts | 68 + packages/types/src/domain/event.ts | 48 + packages/types/src/domain/gamification.ts | 72 + packages/types/src/domain/profile-view.ts | 17 + packages/types/src/domain/program.ts | 23 + packages/types/src/domain/resource.ts | 32 + packages/types/src/domain/scholarship.ts | 28 + packages/types/src/domain/student.ts | 207 + packages/types/src/domain/types.ts | 142 + packages/types/src/index.ts | 12 + packages/types/src/shared/types.ts | 1 + packages/types/src/shared/zod.ts | 31 + packages/types/tsconfig.json | 3 + packages/utils/package.json | 14 + packages/utils/src/get-cookie.test.ts | 25 + packages/utils/src/get-cookie.ts | 23 + packages/utils/src/id.ts | 15 + packages/utils/src/iife.test.ts | 13 + packages/utils/src/iife.ts | 20 + packages/utils/src/index.ts | 8 + packages/utils/src/order.ts | 12 + packages/utils/src/pick.test.ts | 10 + packages/utils/src/pick.ts | 31 + packages/utils/src/sleep.test.ts | 12 + packages/utils/src/sleep.ts | 12 + packages/utils/src/to-escaped-string.test.ts | 18 + packages/utils/src/to-escaped-string.ts | 22 + packages/utils/src/to-title-case.test.ts | 47 + packages/utils/src/to-title-case.ts | 55 + packages/utils/tsconfig.json | 4 + turbo.json | 21 + yarn.lock | 11215 ++++++++++++++++ 525 files changed, 49820 insertions(+), 1 deletion(-) create mode 100644 .eslintrc.js create mode 100644 .github/CODEOWNERS create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore create mode 100644 .prettierrc.js create mode 100644 .vscode/settings.json create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE.md create mode 100644 apps/admin-dashboard/.env.example create mode 100644 apps/admin-dashboard/.eslintrc.js create mode 100644 apps/admin-dashboard/app/entry.client.tsx create mode 100644 apps/admin-dashboard/app/entry.server.tsx create mode 100644 apps/admin-dashboard/app/root.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard._index.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.admins.add.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.applications.$id._index.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.applications.$id.email.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.applications.$id.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.applications.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.bull.$queue._index.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.bull.$queue.jobs.$id.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.bull.$queue.jobs.add.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.bull.$queue.jobs.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.bull.$queue.repeatables.add.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.bull.$queue.repeatables.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.bull.$queue.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.bull._index.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.bull.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.events.$id.import.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.events.create.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.events.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.gamification.activities.$id.archive.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.gamification.activities.$id.edit.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.gamification.activities.add.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.gamification.activities.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.icebreakers.add.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.logout.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.onboarding-sessions.$id.add-attendees.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.onboarding-sessions.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.onboarding-sessions.upload.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.programs.create.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.resources.create.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.schools.create.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.schools.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.students.$id.activate.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.students.$id.email.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.students.$id.points.grant.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.students.$id.remove.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.students.import.programs.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.students.import.resources.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.students.import.scholarships.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.students.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.surveys.$id.import.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.surveys.create.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.surveys.tsx create mode 100644 apps/admin-dashboard/app/routes/_dashboard.tsx create mode 100644 apps/admin-dashboard/app/routes/health.tsx create mode 100644 apps/admin-dashboard/app/routes/login._index.tsx create mode 100644 apps/admin-dashboard/app/routes/login.oauth.tsx create mode 100644 apps/admin-dashboard/app/routes/login.otp.send.tsx create mode 100644 apps/admin-dashboard/app/routes/login.otp.verify.tsx create mode 100644 apps/admin-dashboard/app/routes/login.tsx create mode 100644 apps/admin-dashboard/app/routes/members.search.tsx create mode 100644 apps/admin-dashboard/app/shared/components/activity-form.tsx create mode 100644 apps/admin-dashboard/app/shared/components/card.tsx create mode 100644 apps/admin-dashboard/app/shared/components/onboarding-session-form.tsx create mode 100644 apps/admin-dashboard/app/shared/constants.server.ts create mode 100644 apps/admin-dashboard/app/shared/constants.ts create mode 100644 apps/admin-dashboard/app/shared/cookies.server.ts create mode 100644 apps/admin-dashboard/app/shared/core.server.ts create mode 100644 apps/admin-dashboard/app/shared/core.ui.ts create mode 100644 apps/admin-dashboard/app/shared/queries/admin.ts create mode 100644 apps/admin-dashboard/app/shared/queries/student.ts create mode 100644 apps/admin-dashboard/app/shared/session.server.ts create mode 100644 apps/admin-dashboard/app/tailwind.css create mode 100644 apps/admin-dashboard/env.d.ts create mode 100644 apps/admin-dashboard/global.d.ts create mode 100644 apps/admin-dashboard/package.json create mode 100644 apps/admin-dashboard/postcss.config.mjs create mode 100644 apps/admin-dashboard/public/favicon.ico create mode 100644 apps/admin-dashboard/public/images/colorstack-background.png create mode 100644 apps/admin-dashboard/public/images/colorstack-wordmark.png create mode 100644 apps/admin-dashboard/public/images/linkedin.png create mode 100644 apps/admin-dashboard/railway.json create mode 100644 apps/admin-dashboard/tailwind.config.js create mode 100644 apps/admin-dashboard/tsconfig.json create mode 100644 apps/admin-dashboard/vite.config.ts create mode 100644 apps/api/.env.example create mode 100644 apps/api/.eslintrc.js create mode 100644 apps/api/package.json create mode 100644 apps/api/railway.json create mode 100644 apps/api/src/main.ts create mode 100644 apps/api/src/routers/health.router.ts create mode 100644 apps/api/src/routers/oauth.router.ts create mode 100644 apps/api/src/routers/slack-event.router.ts create mode 100644 apps/api/src/routers/slack-event.types.ts create mode 100644 apps/api/src/shared/env.ts create mode 100644 apps/api/src/shared/types.ts create mode 100644 apps/api/tsconfig.json create mode 100644 apps/member-profile/.env.example create mode 100644 apps/member-profile/.eslintrc.js create mode 100644 apps/member-profile/app/entry.client.tsx create mode 100644 apps/member-profile/app/entry.server.tsx create mode 100644 apps/member-profile/app/root.tsx create mode 100644 apps/member-profile/app/routes/_index.tsx create mode 100644 apps/member-profile/app/routes/_profile.directory._index.tsx create mode 100644 apps/member-profile/app/routes/_profile.directory.join.1.tsx create mode 100644 apps/member-profile/app/routes/_profile.directory.join.2.tsx create mode 100644 apps/member-profile/app/routes/_profile.directory.join.3.tsx create mode 100644 apps/member-profile/app/routes/_profile.directory.join.4.tsx create mode 100644 apps/member-profile/app/routes/_profile.directory.join._index.tsx create mode 100644 apps/member-profile/app/routes/_profile.directory.join.finish.tsx create mode 100644 apps/member-profile/app/routes/_profile.directory.join.tsx create mode 100644 apps/member-profile/app/routes/_profile.directory.tsx create mode 100644 apps/member-profile/app/routes/_profile.directory_.$id.tsx create mode 100644 apps/member-profile/app/routes/_profile.events._index.tsx create mode 100644 apps/member-profile/app/routes/_profile.events.past.$id.attendees.tsx create mode 100644 apps/member-profile/app/routes/_profile.events.past.tsx create mode 100644 apps/member-profile/app/routes/_profile.events.tsx create mode 100644 apps/member-profile/app/routes/_profile.events.upcoming.$id.register.tsx create mode 100644 apps/member-profile/app/routes/_profile.events.upcoming.$id.registrations.tsx create mode 100644 apps/member-profile/app/routes/_profile.events.upcoming.tsx create mode 100644 apps/member-profile/app/routes/_profile.home.claim-swag-pack._index.tsx create mode 100644 apps/member-profile/app/routes/_profile.home.claim-swag-pack.confirmation.tsx create mode 100644 apps/member-profile/app/routes/_profile.home.claim-swag-pack.tsx create mode 100644 apps/member-profile/app/routes/_profile.home.tsx create mode 100644 apps/member-profile/app/routes/_profile.logout.tsx create mode 100644 apps/member-profile/app/routes/_profile.points.tsx create mode 100644 apps/member-profile/app/routes/_profile.profile._index.tsx create mode 100644 apps/member-profile/app/routes/_profile.profile.education.$id.delete.tsx create mode 100644 apps/member-profile/app/routes/_profile.profile.education.$id.edit.tsx create mode 100644 apps/member-profile/app/routes/_profile.profile.education.add.tsx create mode 100644 apps/member-profile/app/routes/_profile.profile.education.tsx create mode 100644 apps/member-profile/app/routes/_profile.profile.emails.add.finish.tsx create mode 100644 apps/member-profile/app/routes/_profile.profile.emails.add.start.tsx create mode 100644 apps/member-profile/app/routes/_profile.profile.emails.change-primary.tsx create mode 100644 apps/member-profile/app/routes/_profile.profile.emails.tsx create mode 100644 apps/member-profile/app/routes/_profile.profile.general.tsx create mode 100644 apps/member-profile/app/routes/_profile.profile.icebreakers.tsx create mode 100644 apps/member-profile/app/routes/_profile.profile.personal.tsx create mode 100644 apps/member-profile/app/routes/_profile.profile.socials.tsx create mode 100644 apps/member-profile/app/routes/_profile.profile.tsx create mode 100644 apps/member-profile/app/routes/_profile.profile.work.$id.delete.tsx create mode 100644 apps/member-profile/app/routes/_profile.profile.work.$id.edit.tsx create mode 100644 apps/member-profile/app/routes/_profile.profile.work.add.tsx create mode 100644 apps/member-profile/app/routes/_profile.profile.work.tsx create mode 100644 apps/member-profile/app/routes/_profile.tsx create mode 100644 apps/member-profile/app/routes/_public.apply._index.tsx create mode 100644 apps/member-profile/app/routes/_public.apply.thank-you.tsx create mode 100644 apps/member-profile/app/routes/_public.apply.tsx create mode 100644 apps/member-profile/app/routes/_public.claim-swag-pack.tsx create mode 100644 apps/member-profile/app/routes/_public.login._index.tsx create mode 100644 apps/member-profile/app/routes/_public.login.oauth.tsx create mode 100644 apps/member-profile/app/routes/_public.login.otp.send.tsx create mode 100644 apps/member-profile/app/routes/_public.login.otp.verify.tsx create mode 100644 apps/member-profile/app/routes/_public.login.tsx create mode 100644 apps/member-profile/app/routes/_public.tsx create mode 100644 apps/member-profile/app/routes/cities.$id.tsx create mode 100644 apps/member-profile/app/routes/cities.autocomplete.tsx create mode 100644 apps/member-profile/app/routes/companies.tsx create mode 100644 apps/member-profile/app/routes/countries.search.tsx create mode 100644 apps/member-profile/app/routes/health.tsx create mode 100644 apps/member-profile/app/routes/schools.tsx create mode 100644 apps/member-profile/app/shared/components/card.tsx create mode 100644 apps/member-profile/app/shared/components/city-combobox.tsx create mode 100644 apps/member-profile/app/shared/components/company-combobox.tsx create mode 100644 apps/member-profile/app/shared/components/education-experience.tsx create mode 100644 apps/member-profile/app/shared/components/education-form.tsx create mode 100644 apps/member-profile/app/shared/components/empty-state.tsx create mode 100644 apps/member-profile/app/shared/components/ethnicity-combobox.tsx create mode 100644 apps/member-profile/app/shared/components/event.tsx create mode 100644 apps/member-profile/app/shared/components/profile.general.tsx create mode 100644 apps/member-profile/app/shared/components/profile.icebreakers.tsx create mode 100644 apps/member-profile/app/shared/components/profile.personal.tsx create mode 100644 apps/member-profile/app/shared/components/profile.tsx create mode 100644 apps/member-profile/app/shared/constants.server.ts create mode 100644 apps/member-profile/app/shared/constants.ts create mode 100644 apps/member-profile/app/shared/cookies.server.ts create mode 100644 apps/member-profile/app/shared/core.server.ts create mode 100644 apps/member-profile/app/shared/core.ui.ts create mode 100644 apps/member-profile/app/shared/mixpanel.server.ts create mode 100644 apps/member-profile/app/shared/queries/index.ts create mode 100644 apps/member-profile/app/shared/session.server.ts create mode 100644 apps/member-profile/app/shared/url.utils.ts create mode 100644 apps/member-profile/app/shared/utils/format.utils.ts create mode 100644 apps/member-profile/app/tailwind.css create mode 100644 apps/member-profile/env.d.ts create mode 100644 apps/member-profile/global.d.ts create mode 100644 apps/member-profile/package.json create mode 100644 apps/member-profile/postcss.config.mjs create mode 100644 apps/member-profile/public/apple-touch-icon.png create mode 100644 apps/member-profile/public/favicon.ico create mode 100644 apps/member-profile/public/images/calendly.svg create mode 100644 apps/member-profile/public/images/colorstack-background.png create mode 100644 apps/member-profile/public/images/colorstack-notebook-navy.png create mode 100644 apps/member-profile/public/images/colorstack-shirt-black-1.png create mode 100644 apps/member-profile/public/images/colorstack-shirt-black-2.png create mode 100644 apps/member-profile/public/images/colorstack-wordmark.png create mode 100644 apps/member-profile/public/images/github.svg create mode 100644 apps/member-profile/public/images/instagram.svg create mode 100644 apps/member-profile/public/images/linkedin.png create mode 100644 apps/member-profile/public/images/member-profile-home.png create mode 100644 apps/member-profile/public/images/slack.svg create mode 100644 apps/member-profile/public/images/university.png create mode 100644 apps/member-profile/public/images/x.png create mode 100644 apps/member-profile/railway.json create mode 100644 apps/member-profile/tailwind.config.js create mode 100644 apps/member-profile/tsconfig.json create mode 100644 apps/member-profile/vite.config.ts create mode 100644 config/eslint/base.js create mode 100644 config/eslint/package.json create mode 100644 config/tsconfig/base.json create mode 100644 config/tsconfig/package.json create mode 100644 config/tsconfig/react-library.json create mode 100644 config/tsconfig/remix.json create mode 100644 docs/how-to-enable-integrations.md create mode 100644 docs/how-to-implement-a-database-migration.md create mode 100644 package.json create mode 100644 packages/core-ui/package.json create mode 100644 packages/core-ui/rollup.config.js create mode 100644 packages/core-ui/src/css/_breakpoints.scss create mode 100644 packages/core-ui/src/css/shared.css create mode 100644 packages/core-ui/src/hooks/use-delayed-value.ts create mode 100644 packages/core-ui/src/hooks/use-hydrated.ts create mode 100644 packages/core-ui/src/hooks/use-on-click-outside.ts create mode 100644 packages/core-ui/src/hooks/use-search-params.ts create mode 100644 packages/core-ui/src/index.ts create mode 100644 packages/core-ui/src/ui/address.tsx create mode 100644 packages/core-ui/src/ui/button.tsx create mode 100644 packages/core-ui/src/ui/checkbox/checkbox.module.scss create mode 100644 packages/core-ui/src/ui/checkbox/checkbox.tsx create mode 100644 packages/core-ui/src/ui/combobox-popover.tsx create mode 100644 packages/core-ui/src/ui/combobox.tsx create mode 100644 packages/core-ui/src/ui/date-picker.tsx create mode 100644 packages/core-ui/src/ui/divider.tsx create mode 100644 packages/core-ui/src/ui/dropdown/dropdown.module.scss create mode 100644 packages/core-ui/src/ui/dropdown/dropdown.tsx create mode 100644 packages/core-ui/src/ui/form.tsx create mode 100644 packages/core-ui/src/ui/icon-button.tsx create mode 100644 packages/core-ui/src/ui/input.tsx create mode 100644 packages/core-ui/src/ui/link.tsx create mode 100644 packages/core-ui/src/ui/modal/modal.module.scss create mode 100644 packages/core-ui/src/ui/modal/modal.tsx create mode 100644 packages/core-ui/src/ui/multi-combobox.tsx create mode 100644 packages/core-ui/src/ui/pagination.tsx create mode 100644 packages/core-ui/src/ui/pill.tsx create mode 100644 packages/core-ui/src/ui/radio/radio.module.scss create mode 100644 packages/core-ui/src/ui/radio/radio.tsx create mode 100644 packages/core-ui/src/ui/search-bar.tsx create mode 100644 packages/core-ui/src/ui/select/select.module.scss create mode 100644 packages/core-ui/src/ui/select/select.tsx create mode 100644 packages/core-ui/src/ui/spinner.tsx create mode 100644 packages/core-ui/src/ui/table.tsx create mode 100644 packages/core-ui/src/ui/text.tsx create mode 100644 packages/core-ui/src/ui/textarea.tsx create mode 100644 packages/core-ui/src/ui/toast/toast.module.scss create mode 100644 packages/core-ui/src/ui/toast/toast.tsx create mode 100644 packages/core-ui/src/utils/constants.ts create mode 100644 packages/core-ui/src/utils/cx.ts create mode 100644 packages/core-ui/src/utils/zod.ts create mode 100644 packages/core-ui/tsconfig.json create mode 100644 packages/core-ui/types.d.ts create mode 100644 packages/core/.env.example create mode 100644 packages/core/package.json create mode 100644 packages/core/src/admin-dashboard.server.ts create mode 100644 packages/core/src/admin-dashboard.ui.ts create mode 100644 packages/core/src/api.ts create mode 100644 packages/core/src/infrastructure/bull/bull.ts create mode 100644 packages/core/src/infrastructure/bull/bull.types.ts create mode 100644 packages/core/src/infrastructure/bull/use-cases/job.ts create mode 100644 packages/core/src/infrastructure/bull/use-cases/register-worker.ts create mode 100644 packages/core/src/infrastructure/database/index.ts create mode 100644 packages/core/src/infrastructure/database/migrations/2024-01-29T17:23:16Z-init.ts create mode 100644 packages/core/src/infrastructure/database/migrations/2024-01-29T19:05:29Z-birthdate.ts create mode 100644 packages/core/src/infrastructure/database/migrations/2024-02-12T21:28:42Z-fix-removal.ts create mode 100644 packages/core/src/infrastructure/database/migrations/2024-03-11T10:33:01Z-job_offers.ts create mode 100644 packages/core/src/infrastructure/database/migrations/2024-03-18T17:06:13Z-birthday-notification.ts create mode 100644 packages/core/src/infrastructure/database/migrations/2024-03-18T19:45:26Z-birthday-default.ts create mode 100644 packages/core/src/infrastructure/database/scripts/migrate.ts create mode 100644 packages/core/src/infrastructure/database/scripts/seed.ts create mode 100644 packages/core/src/infrastructure/database/shared/create-database-connection.ts create mode 100644 packages/core/src/infrastructure/database/shared/migrate.ts create mode 100644 packages/core/src/infrastructure/database/vitest-environment-kysely.ts create mode 100644 packages/core/src/infrastructure/redis.ts create mode 100644 packages/core/src/member-profile.server.ts create mode 100644 packages/core/src/member-profile.ui.ts create mode 100644 packages/core/src/modules/active-status/queries/get-active-streak-leaderboard-position.ts create mode 100644 packages/core/src/modules/active-status/queries/get-active-streak-leaderboard.ts create mode 100644 packages/core/src/modules/active-status/queries/get-active-streak.ts create mode 100644 packages/core/src/modules/active-status/shared/active-status.shared.ts create mode 100644 packages/core/src/modules/active-status/use-cases/backfill-active-statuses.ts create mode 100644 packages/core/src/modules/active-status/use-cases/create-new-active-statuses.ts create mode 100644 packages/core/src/modules/admin/admin.types.ts create mode 100644 packages/core/src/modules/admin/use-cases/add-admin.ts create mode 100644 packages/core/src/modules/airtable/airtable.shared.ts create mode 100644 packages/core/src/modules/airtable/airtable.worker.ts create mode 100644 packages/core/src/modules/airtable/use-cases/create-airtable-member-record.ts create mode 100644 packages/core/src/modules/airtable/use-cases/create-airtable-record.ts create mode 100644 packages/core/src/modules/airtable/use-cases/delete-airtable-record.ts create mode 100644 packages/core/src/modules/airtable/use-cases/update-airtable-record.ts create mode 100644 packages/core/src/modules/application/application.worker.ts create mode 100644 packages/core/src/modules/application/events/application-accepted.ts create mode 100644 packages/core/src/modules/application/events/application-created.ts create mode 100644 packages/core/src/modules/application/events/application-rejected.ts create mode 100644 packages/core/src/modules/application/queries/count-pending-applications.ts create mode 100644 packages/core/src/modules/application/queries/get-application.ts create mode 100644 packages/core/src/modules/application/queries/list-applications.ts create mode 100644 packages/core/src/modules/application/ui/application-form.tsx create mode 100644 packages/core/src/modules/application/ui/major-combobox.tsx create mode 100644 packages/core/src/modules/application/ui/school-combobox.tsx create mode 100644 packages/core/src/modules/application/use-cases/accept-application.ts create mode 100644 packages/core/src/modules/application/use-cases/apply.ts create mode 100644 packages/core/src/modules/application/use-cases/reject-application.ts create mode 100644 packages/core/src/modules/application/use-cases/review-application.ts create mode 100644 packages/core/src/modules/application/use-cases/update-application-email.ts create mode 100644 packages/core/src/modules/authentication/authentication.types.ts create mode 100644 packages/core/src/modules/authentication/oauth.service.ts create mode 100644 packages/core/src/modules/authentication/one-time-code.worker.ts create mode 100644 packages/core/src/modules/authentication/services/google-oauth.service.ts create mode 100644 packages/core/src/modules/authentication/services/slack-oauth.service.ts create mode 100644 packages/core/src/modules/authentication/shared/oauth.utils.ts create mode 100644 packages/core/src/modules/authentication/ui/one-time-code-form.tsx create mode 100644 packages/core/src/modules/authentication/use-cases/expire-one-time-code.ts create mode 100644 packages/core/src/modules/authentication/use-cases/login-with-oauth.ts create mode 100644 packages/core/src/modules/authentication/use-cases/send-one-time-code.ts create mode 100644 packages/core/src/modules/authentication/use-cases/verify-one-time-code.ts create mode 100644 packages/core/src/modules/education/education.types.ts create mode 100644 packages/core/src/modules/education/education.worker.ts create mode 100644 packages/core/src/modules/education/events/education-added.ts create mode 100644 packages/core/src/modules/education/events/education-deleted.ts create mode 100644 packages/core/src/modules/education/use-cases/add-education.ts create mode 100644 packages/core/src/modules/education/use-cases/check-most-recent-education.ts create mode 100644 packages/core/src/modules/education/use-cases/create-school.ts create mode 100644 packages/core/src/modules/education/use-cases/delete-education.ts create mode 100644 packages/core/src/modules/education/use-cases/edit-education.ts create mode 100644 packages/core/src/modules/employment/employment.types.ts create mode 100644 packages/core/src/modules/employment/employment.worker.ts create mode 100644 packages/core/src/modules/employment/events/work-experience-added.ts create mode 100644 packages/core/src/modules/employment/events/work-experience-deleted.ts create mode 100644 packages/core/src/modules/employment/queries/get-crunchbase-organization.ts create mode 100644 packages/core/src/modules/employment/queries/get-work-experience.ts create mode 100644 packages/core/src/modules/employment/queries/list-work-experiences.ts create mode 100644 packages/core/src/modules/employment/queries/search-crunchbase-organizations.ts create mode 100644 packages/core/src/modules/employment/shared/crunchbase.utils.ts create mode 100644 packages/core/src/modules/employment/ui/work-experience.tsx create mode 100644 packages/core/src/modules/employment/ui/work-form.tsx create mode 100644 packages/core/src/modules/employment/use-cases/add-work-experience.ts create mode 100644 packages/core/src/modules/employment/use-cases/delete-work-experience.ts create mode 100644 packages/core/src/modules/employment/use-cases/edit-work-experience.ts create mode 100644 packages/core/src/modules/employment/use-cases/save-company-if-necessary.test.ts create mode 100644 packages/core/src/modules/employment/use-cases/save-company-if-necessary.ts create mode 100644 packages/core/src/modules/event/airmeet-event.service.ts create mode 100644 packages/core/src/modules/event/event.worker.ts create mode 100644 packages/core/src/modules/event/events/event-attended.ts create mode 100644 packages/core/src/modules/event/events/event-registered.ts create mode 100644 packages/core/src/modules/event/queries/count-past-events.ts create mode 100644 packages/core/src/modules/event/queries/count-upcoming-events.ts create mode 100644 packages/core/src/modules/event/queries/get-event.ts create mode 100644 packages/core/src/modules/event/queries/get-events-attended-count.ts create mode 100644 packages/core/src/modules/event/queries/list-events.ts create mode 100644 packages/core/src/modules/event/use-cases/create-event.ts create mode 100644 packages/core/src/modules/event/use-cases/register-for-event.ts create mode 100644 packages/core/src/modules/event/use-cases/sync-airmeet-event.ts create mode 100644 packages/core/src/modules/event/use-cases/sync-recent-airmeet-events.ts create mode 100644 packages/core/src/modules/feature-flag/feature-flag.shared.ts create mode 100644 packages/core/src/modules/feature-flag/queries/is-feature-flag-enabled.ts create mode 100644 packages/core/src/modules/feature-flag/use-cases/initialize-feature-flag-server.ts create mode 100644 packages/core/src/modules/gamification/gamification.worker.ts create mode 100644 packages/core/src/modules/gamification/queries/get-total-points.ts create mode 100644 packages/core/src/modules/gamification/use-cases/archive-activity.ts create mode 100644 packages/core/src/modules/gamification/use-cases/edit-activity.ts create mode 100644 packages/core/src/modules/gamification/use-cases/grant-gamification-points.ts create mode 100644 packages/core/src/modules/gamification/use-cases/revoke-gamification-points.ts create mode 100644 packages/core/src/modules/icebreaker/icebreaker.types.ts create mode 100644 packages/core/src/modules/icebreaker/queries/get-icebreaker-prompts.ts create mode 100644 packages/core/src/modules/icebreaker/queries/get-icebreaker-responses.ts create mode 100644 packages/core/src/modules/icebreaker/use-cases/add-icebreaker-prompt.ts create mode 100644 packages/core/src/modules/icebreaker/use-cases/upsert-icebreaker-responses.ts create mode 100644 packages/core/src/modules/location/location.shared.ts create mode 100644 packages/core/src/modules/location/location.types.ts create mode 100644 packages/core/src/modules/location/queries/get-autocompleted-cities.ts create mode 100644 packages/core/src/modules/location/queries/get-city-details.ts create mode 100644 packages/core/src/modules/mailchimp/email-marketing.shared.ts create mode 100644 packages/core/src/modules/mailchimp/email-marketing.worker.ts create mode 100644 packages/core/src/modules/mailchimp/events/mailchimp-campaign-opened.ts create mode 100644 packages/core/src/modules/mailchimp/mailchimp.types.d.ts create mode 100644 packages/core/src/modules/mailchimp/use-cases/add-mailchimp-list-member.ts create mode 100644 packages/core/src/modules/mailchimp/use-cases/remove-mailchimp-list-member.ts create mode 100644 packages/core/src/modules/mailchimp/use-cases/sync-mailchimp-campaign.ts create mode 100644 packages/core/src/modules/mailchimp/use-cases/sync-mailchimp-list.ts create mode 100644 packages/core/src/modules/mailchimp/use-cases/update-mailchimp-list-member.ts create mode 100644 packages/core/src/modules/member/events/activation-step-completed.ts create mode 100644 packages/core/src/modules/member/events/member-activated.ts create mode 100644 packages/core/src/modules/member/events/member-created.ts create mode 100644 packages/core/src/modules/member/events/member-email-added.ts create mode 100644 packages/core/src/modules/member/events/member-primary-email-changed.ts create mode 100644 packages/core/src/modules/member/events/member-removed.ts create mode 100644 packages/core/src/modules/member/member-email.worker.ts create mode 100644 packages/core/src/modules/member/member.worker.ts create mode 100644 packages/core/src/modules/member/profile.worker.ts create mode 100644 packages/core/src/modules/member/queries/find-member-by-email.ts create mode 100644 packages/core/src/modules/member/use-cases/activate-member.ts create mode 100644 packages/core/src/modules/member/use-cases/backfill-engagement-records.ts create mode 100644 packages/core/src/modules/member/use-cases/join-member-directory.ts create mode 100644 packages/core/src/modules/member/use-cases/send-birthday-notification.ts create mode 100644 packages/core/src/modules/member/use-cases/send-profile-views-notification.ts create mode 100644 packages/core/src/modules/member/use-cases/update-member-email.ts create mode 100644 packages/core/src/modules/member/use-cases/view-member-profile.ts create mode 100644 packages/core/src/modules/notification/notification.worker.ts create mode 100644 packages/core/src/modules/notification/shared/email.utils.ts create mode 100644 packages/core/src/modules/notification/use-cases/send-email.ts create mode 100644 packages/core/src/modules/notification/use-cases/send-slack-notification.ts create mode 100644 packages/core/src/modules/onboarding-session/events/onboarding-session-attended.ts create mode 100644 packages/core/src/modules/onboarding-session/onboarding-session.types.ts create mode 100644 packages/core/src/modules/onboarding-session/onboarding-session.worker.ts create mode 100644 packages/core/src/modules/onboarding-session/use-cases/add-onboarding-session-attendees.ts create mode 100644 packages/core/src/modules/onboarding-session/use-cases/upload-onboarding-session.ts create mode 100644 packages/core/src/modules/sentry/use-cases/report-error.ts create mode 100644 packages/core/src/modules/slack/events/slack-message-added.ts create mode 100644 packages/core/src/modules/slack/events/slack-profile-picture-changed.ts create mode 100644 packages/core/src/modules/slack/events/slack-workspace-joined.ts create mode 100644 packages/core/src/modules/slack/instances/index.ts create mode 100644 packages/core/src/modules/slack/queries/count-messages-sent.ts create mode 100644 packages/core/src/modules/slack/services/slack-admin.service.ts create mode 100644 packages/core/src/modules/slack/services/slack-channel.service.ts create mode 100644 packages/core/src/modules/slack/services/slack-message.service.ts create mode 100644 packages/core/src/modules/slack/services/slack-user.service.ts create mode 100644 packages/core/src/modules/slack/slack.types.ts create mode 100644 packages/core/src/modules/slack/slack.worker.ts create mode 100644 packages/core/src/modules/slack/use-cases/add-slack-message.ts create mode 100644 packages/core/src/modules/slack/use-cases/add-slack-reaction.ts create mode 100644 packages/core/src/modules/slack/use-cases/archive-slack-channel.ts create mode 100644 packages/core/src/modules/slack/use-cases/change-slack-message.ts create mode 100644 packages/core/src/modules/slack/use-cases/create-slack-channel.ts create mode 100644 packages/core/src/modules/slack/use-cases/deactivate-slack-user.ts create mode 100644 packages/core/src/modules/slack/use-cases/delete-slack-channel.ts create mode 100644 packages/core/src/modules/slack/use-cases/delete-slack-message.ts create mode 100644 packages/core/src/modules/slack/use-cases/invite-to-slack-workspace.ts create mode 100644 packages/core/src/modules/slack/use-cases/remove-slack-reaction.ts create mode 100644 packages/core/src/modules/slack/use-cases/rename-slack-channel.ts create mode 100644 packages/core/src/modules/slack/use-cases/unarchive-slack-channel.ts create mode 100644 packages/core/src/modules/survey/events/survey.responded.ts create mode 100644 packages/core/src/modules/survey/survey.types.ts create mode 100644 packages/core/src/modules/survey/survey.worker.ts create mode 100644 packages/core/src/modules/survey/use-cases/create-survey.ts create mode 100644 packages/core/src/modules/survey/use-cases/import-survey-responses.ts create mode 100644 packages/core/src/modules/swag-pack/swag-pack.service.ts create mode 100644 packages/core/src/modules/swag-pack/swag-pack.types.ts create mode 100644 packages/core/src/modules/swag-pack/swag-pack.worker.ts create mode 100644 packages/core/src/modules/swag-pack/use-cases/claim-swag-pack.ts create mode 100644 packages/core/src/modules/swag-pack/use-cases/notify-swag-pack-inventory.ts create mode 100644 packages/core/src/shared/constants.ts create mode 100644 packages/core/src/shared/env.ts create mode 100644 packages/core/src/shared/errors.ts create mode 100644 packages/core/src/shared/types.ts create mode 100644 packages/core/src/shared/utils/auth.utils.ts create mode 100644 packages/core/src/shared/utils/core.utils.ts create mode 100644 packages/core/src/shared/utils/csv.utils.ts create mode 100644 packages/core/src/shared/utils/ip.utils.ts create mode 100644 packages/core/src/shared/utils/rate-limiter.ts create mode 100644 packages/core/src/shared/utils/test.utils.ts create mode 100644 packages/core/src/shared/utils/zod.utils.ts create mode 100644 packages/core/tsconfig.json create mode 100644 packages/core/tsup.config.ts create mode 100644 packages/core/vitest.config.ts create mode 100644 packages/email-templates/emails/application-accepted.tsx create mode 100644 packages/email-templates/emails/application-created.tsx create mode 100644 packages/email-templates/emails/application-rejected.tsx create mode 100644 packages/email-templates/emails/components/email.tsx create mode 100644 packages/email-templates/emails/one-time-code-sent.tsx create mode 100644 packages/email-templates/emails/primary-email-changed.tsx create mode 100644 packages/email-templates/emails/student-activated.tsx create mode 100644 packages/email-templates/emails/student-attended-onboarding.tsx create mode 100644 packages/email-templates/emails/student-removed.tsx create mode 100644 packages/email-templates/package.json create mode 100644 packages/email-templates/src/index.ts create mode 100644 packages/email-templates/src/types.ts create mode 100644 packages/email-templates/tsconfig.json create mode 100644 packages/feature-ui/package.json create mode 100644 packages/feature-ui/src/index.ts create mode 100644 packages/feature-ui/src/ui/dashboard.tsx create mode 100644 packages/feature-ui/src/ui/login.tsx create mode 100644 packages/feature-ui/src/ui/profile-picture.tsx create mode 100644 packages/feature-ui/src/ui/public.tsx create mode 100644 packages/feature-ui/tsconfig.json create mode 100644 packages/types/package.json create mode 100644 packages/types/src/domain/application.ts create mode 100644 packages/types/src/domain/email-marketing.ts create mode 100644 packages/types/src/domain/event.ts create mode 100644 packages/types/src/domain/gamification.ts create mode 100644 packages/types/src/domain/profile-view.ts create mode 100644 packages/types/src/domain/program.ts create mode 100644 packages/types/src/domain/resource.ts create mode 100644 packages/types/src/domain/scholarship.ts create mode 100644 packages/types/src/domain/student.ts create mode 100644 packages/types/src/domain/types.ts create mode 100644 packages/types/src/index.ts create mode 100644 packages/types/src/shared/types.ts create mode 100644 packages/types/src/shared/zod.ts create mode 100644 packages/types/tsconfig.json create mode 100644 packages/utils/package.json create mode 100644 packages/utils/src/get-cookie.test.ts create mode 100644 packages/utils/src/get-cookie.ts create mode 100644 packages/utils/src/id.ts create mode 100644 packages/utils/src/iife.test.ts create mode 100644 packages/utils/src/iife.ts create mode 100644 packages/utils/src/index.ts create mode 100644 packages/utils/src/order.ts create mode 100644 packages/utils/src/pick.test.ts create mode 100644 packages/utils/src/pick.ts create mode 100644 packages/utils/src/sleep.test.ts create mode 100644 packages/utils/src/sleep.ts create mode 100644 packages/utils/src/to-escaped-string.test.ts create mode 100644 packages/utils/src/to-escaped-string.ts create mode 100644 packages/utils/src/to-title-case.test.ts create mode 100644 packages/utils/src/to-title-case.ts create mode 100644 packages/utils/tsconfig.json create mode 100644 turbo.json create mode 100644 yarn.lock diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 000000000..fbce0b866 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,4 @@ +module.exports = { + extends: ['colorstack'], + root: true, +}; diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..173dd969c --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @ramiAbdou \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..6de00d586 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,32 @@ +--- +name: Bug Report 🐞 +about: Report any issues with the platform. +title: '' +labels: bug +assignees: '' +--- + +### Description + +A clear and concise description of what the bug is. + +### Steps to Reproduce + +Steps to reproduce the behavior: + +1. Go to '...'. +2. Click on '...'. +3. Scroll down to '...'. +4. See error. + +### Expected Behavior + +A clear and concise description of what you expected to happen. + +### Screenshots + +If applicable, add screenshots to help explain your problem. + +### Additional Context + +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..589b32772 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,4 @@ +contact_links: + - name: Ask a Question ❓ + url: https://colorstack-family.slack.com + about: Ask a general question about the codebase in our Slack community. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..1d795a967 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,19 @@ +--- +name: Feature Request 🙏 +about: Suggest a feature to have in ColorStack. +title: '' +labels: feature +assignees: '' +--- + +### Description + +A clear and concise description of what the feature should be. + +### Problem / Value Proposition + +What problem does this solve? What value does it add to ColorStack? + +### Additional Context + +Add any other context about the problem here. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..3f0282aa3 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,23 @@ +## Description ✏️ + +Closes #xxx + +Describe what this PR does. + +- Bullet points are helpful. +- Screenshots are helpful, if applicable. + +## Type of Change 🐞 + +- [ ] Feature - A non-breaking change which adds functionality. +- [ ] Fix - A non-breaking change which fixes an issue. +- [ ] Refactor - A change that neither fixes a bug nor adds a feature. +- [ ] Documentation - A change only to in-code or markdown documentation. +- [ ] Tests - A change that adds missing unit/integration tests. +- [ ] Chore - A change that is likely none of the above. + +## Checklist ✅ + +- [ ] I have done a self-review of my code. +- [ ] I have manually tested my code (if applicable). +- [ ] I have added/updated any relevant documentation (if applicable). diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..003538707 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,75 @@ +name: Continuous Integration + +on: + pull_request: + types: [opened, synchronize] + +jobs: + build: + name: Lint, Build and Test + runs-on: ubuntu-latest + timeout-minutes: 15 + + services: + postgres: + image: postgres + env: + POSTGRES_DB: colorstack + POSTGRES_PASSWORD: password + POSTGRES_USER: username + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready --health-interval 10s --health-timeout 5s + --health-retries 5 + redis: + image: redis + ports: + - 6379:6379 + options: >- + --health-cmd "redis-cli ping" --health-interval 10s --health-timeout + 5s --health-retries 5 + + env: + DATABASE_URL: postgres://username:password@localhost:5432/colorstack + REDIS_URL: redis://localhost:6379 + + steps: + - name: Checkout repository code + uses: actions/checkout@v4 + + - name: Cache Turborepo setup + uses: actions/cache@v4 + with: + # When running turbo commands, we use `.turbo` as the cache directory. + # See the root `package.json` for reference. + path: .turbo + + key: ${{ runner.os }}-turbo-${{ github.sha }} + + # This is how GitHub Actions restores the cache. Because we only + # the prefix of the key (and not the `github.sha`), this will allow + # us to hit the cache on any CI runs on commit on any branch. + restore-keys: | + ${{ runner.os }}-turbo- + + - name: Setup Node.js 20 + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'yarn' + + - name: Install dependencies + run: yarn install --frozen-lockfile + + - name: Run database migrations and generate types + run: yarn db:migrate + + - name: Lint + run: yarn lint + + - name: Build all packages and applications + run: yarn build + + - name: Run tests + run: yarn test diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..814030a8f --- /dev/null +++ b/.gitignore @@ -0,0 +1,36 @@ +# Dependencies + +node_modules + +# Environment Variables + +.env + +# Turborepo + +.turbo + +# React Email + +.react-email + +# Remix Run + +.cache + +# Build + +build +dist +tsconfig.tsbuildinfo + + +# Debugging + +yarn-debug.log* +yarn-error.log* + + +# Miscelleanous + +.DS_Store diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 000000000..9118330f0 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,8 @@ +module.exports = { + printWidth: 80, + proseWrap: 'always', + semi: true, + singleQuote: true, + trailingComma: 'es5', + tailwindFunctions: ['cx'], +}; diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..1c3864341 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,22 @@ +{ + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + }, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.rulers": [80], + "editor.quickSuggestions": { "strings": "on" }, + "eslint.workingDirectories": ["./apps/*", "./config/*", "./packages/*"], + "typescript.preferences.importModuleSpecifier": "relative", + "typescript.tsdk": "node_modules/typescript/lib", + "[typescript][typescriptreact]": { + "editor.codeActionsOnSave": { + "source.fixAll": "explicit", + "source.organizeImports": "explicit" + } + }, + "tailwindCSS.experimental.classRegex": [ + ["cx\\(([^)]+)\\)", "'([^']*)'"], + ["cx\\(([^)]+)\\)", "`([^`]*)`"] + ] +} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..bd60b426c --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,132 @@ +# Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +- Demonstrating empathy and kindness toward other people. +- Being respectful of differing opinions, viewpoints, and experiences. +- Giving and gracefully accepting constructive feedback. +- Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience. +- Focusing on what is best not just for us as individuals, but for the overall + community. + +Examples of unacceptable behavior include: + +- The use of sexualized language or imagery, and sexual attention or advances of + any kind. +- Trolling, insulting or derogatory comments, and personal or political attacks. +- Public or private harassment. +- Publishing others' private information, such as a physical or email address, + without their explicit permission. +- Other conduct which could reasonably be considered inappropriate in a + professional setting. + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official email address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +rami@colorstack.org. All complaints will be reviewed and investigated promptly +and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder][mozilla coc]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][faq]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[mozilla coc]: https://github.com/mozilla/diversity +[faq]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..1f8b66d64 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,195 @@ +# Contributing + +First off, thank you for taking the time to contribute! 🥳 ColorStack is nothing +without its community, and that certainly extends to the software that we build. +This is a big team effort! + +## Deciding What to Work On + +You can start by browsing through our list of +[issues](https://github.com/colorstackorg/colorstack/issues) or creating your +own issue that would improve our product. Once you've decided on an issue, leave +a comment and wait to get approval from one of our codebase admins - this helps +avoid multiple people working on this same issue. + +## Making a Pull Request + +Some things to keep in mind when making a pull request: + +- The target branch in our repository is `main`. +- Fill out the PR template accordingly. +- The name of the PR should: + - Start with one of the following prefixes: + - `feat`: A non-breaking change which adds functionality. + - `fix`: A non-breaking change which fixes an issue. + - `refactor`: A change that neither fixes a bug nor adds a feature. + - `docs`: A change only to in-code or markdown documentation. + - `test`: A change that adds missing tests. + - `chore`: A change that is likely none of the above. + - Be present tense (ie: "Fix", not "Fixed"). + - Start with a verb (ie: "Fix ....", "Add ...", "Implement ..."). + - Have an emoji at the end of it (we like color around here). 🔥 +- Each PR should be attached to an issue, so be sure to add this to the PR + description: + ``` + Closes #. + ``` + See more about + [linking a pull request to an issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue). +- A PR can only be merged (by a maintainer) if: + - A maintainer has reviewed and approved it. + - All CI checks have passed. See [this](./.github/workflows/ci.yml) workflow + for more details. + - All branches are up to date before merging. + - All conversations are resolved. + +## Local Development + +To get started with local development, please follow these simple steps. + +### Prerequisites + +Please ensure that you have the following software on your machine: + +- [Node.js](https://nodejs.org/en/download/package-manager) (v20.x) +- [Yarn](https://classic.yarnpkg.com/lang/en/docs/install) (v1) +- [PostgreSQL](https://www.postgresql.org/download/) (v15.x) +- [Redis](https://redis.io/docs/install/install-redis/) + +### Fork and Clone Repository + +1. [Fork](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo) + the repository to your own GitHub account. +2. [Clone](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) + the repository to your local machine. + ``` + git clone https://github.com//colorstack.git + ``` +3. Create a new branch. + ``` + git checkout -b YOUR_BRANCH_NAME + ``` +4. Install all project dependencies. + + ```sh + yarn + ``` + +### Environment Variables + +Set up your environment variable files by duplicating `.env.example` to `.env` +in a few places: + +- `/apps/admin-dashboard/.env.example` +- `/apps/api/.env.example` +- `/apps/member-profile/.env.example` +- `/packages/core/.env.example` + +You'll notice that a lot of environment variables are empty. Most of these empty +variables are tied to the 3rd party integrations we have with platforms such as +Postmark for sending emails and Google for authentication. If you would like to +enable these integrations in development, please see the +[How to Enable Integrations](./docs/how-to-enable-integrations.md) +documentation. + +### Database Setup + +You'll need to make sure that Postgres and Redis are running in the background. + +#### Postgres Setup + +Once Postgres is running, you can connect to it by running: + +```sh +psql +``` + +You'll then need to create 2 Postgres databases locally named `colorstack` and +`colorstack-test`. Within the `psql` terminal, run: + +```postgresql +CREATE DATABASE colorstack; +CREATE DATABASE colorstack-test; +``` + +You should now be able to connect to each database like this: + +```sh +psql colorstack +``` + +#### Executing Database Migrations + +To execute the database migrations, run: + +```sh +yarn db:migrate +``` + +To verify that the migration was executed successfully, connect to your Postgres +database and run: + +```sh +\d +``` + +You should see a bunch of SQL tables! + +#### Seeding the Database + +Now that we have some tables, we're ready to add some seed data in our database, +which will enable you to log into the Admin Dashboard and Member Profile. Run: + +```sh +yarn workspace @colorstack/core db:seed +``` + +Follow the prompt to add your email, and you will now be able to log into both +applications. + +### Building the Project + +You can build the project by running: + +```sh +yarn build +``` + +### Running the Applications + +To run all of our _packages and applications_, you can run: + +```sh +yarn dev +``` + +To run all of our _applications_, you can run: + +```sh +yarn dev:apps +``` + +To run a _specific package or application_, you can use the `--filter` flag like +this: + +```sh +yarn dev --filter=api +``` + +### Editor Setup + +Surprise, surprise. We use [VSCode](https://code.visualstudio.com/download) to +write code! After you download it, we'll need to enable some extensions to make +life a bit easier: + +- [Auto Rename Tag](https://marketplace.visualstudio.com/items?itemName=formulahendry.auto-rename-tag) +- [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) +- [Live Share](https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare) +- [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) +- [Tailwind IntelliSense](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss) +- [Typescript Importer](https://marketplace.visualstudio.com/items?itemName=pmneo.tsimporter) + +## License + +By contributing your code to the this GitHub repository, you agree to license +your contribution under the MIT license. diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 000000000..98f339aeb --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,20 @@ +MIT License + +Copyright (c) 2024 ColorStack + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index e845566c0..3bdfca89d 100644 --- a/README.md +++ b/README.md @@ -1 +1,108 @@ -README +

+ +

+ +

The open-source software that powers the ColorStack community experience. ✊🏿✊🏾✊🏽✊🏼

+ +

+ Website | + Family Application +

+ +Member Profile + +## Applications + +- [**Member Profile**](./apps/member-profile/package.json) - Serves as the home + for a ColorStack member, allowing them to manage their information, find and + connect with other members, as well as events and gamification. +- [**Admin Dashboard**](./apps/admin-dashboard/package.json) - An internal + dashboard that the ColorStack team uses to manage important workflows like + application review. +- [**API**](./apps/api/package.json) - Handles all background jobs as well as + any webhook integrations that we have with external services. + +## Understanding the Codebase + +### Important Tools & Technologies + +Here is a list of important tools and technologies that power the ColorStack +codebase: + +- [BullMQ](https://docs.bullmq.io) to queue and process jobs asynchronously (in + the background). +- [Kysely](https://kysely.dev) to query our SQL database in a type-safe way. +- [Node.js](https://nodejs.org/en/about)...because yes! +- [PostgreSQL](https://www.postgresql.org/docs/15/index.html) to store all of + our data. +- [Railway](https://railway.app) to host our applications and databases. +- [Redis](https://redis.io) to store simple key/value based data. +- [Remix](https://remix.run)/[React](https://react.dev) to build fast, + accessible and delightful UI experiences. +- [Tailwind](https://tailwindcss.com) because scaling CSS is hard. +- [Turborepo](https://turbo.build/repo) to manage the build system for our + Typescript monorepo. +- [Typescript](https://www.typescriptlang.org) because we like Javascript...and + we like type checking. +- [Zod](https://zod.dev) to validate all of our data and automatically generate + types. + +### Folder Structure + +Here is the structure of our Typescript monorepo: + +``` +apps +|--- admin-dashboard +|--- api +|--- member-profile +packages +|--- core +|--- core-ui +|--- email-templates +|--- feature-ui +|--- types +|--- utils +``` + +The `apps` directory houses all of our applications (see "Applications" +section). + +The `packages` directory contains reusable pieces of code that are used across +our applications. + +- `core`: Nearly all of our business logic, including our database layer and + more. Will eventually colocate feature-based UI next to its related business + logic. +- `core-ui`: Reusable UI components built in React. +- `email-templates`: React-based email templates built with + [Resend](https://resend.com). +- `feature-ui`: Now deprecated, but previously contained more complex UI code. +- `types`: Miscellaneous types shared across applications. +- `utils`: Reusable utility functions, such as `sleep`. + +### CI Pipeline (GitHub Actions) + +To ensure that we don't have any breaking changes, we have a GitHub Actions +workflow that runs, which can block a PR from being merged if certain checks +don't pass. + +For more information on how that CI pipeline works, see +[this](./.github/workflows/ci.yml) file. + +### Deployment + +We use [Railway](https://railway.app) to host our applications as well as our +PostgreSQL and Redis databases. Whenever we make some changes to our `main` +branch, Railway will automatically pick up those changes and deploy a new +version of our applications. + +Each application has a `railway.json` file where we can configure certain +settings and instructions so Railway knows _how and when_ to build/start our +application. See [this](./apps/api/railway.json) file as an example. For a full +list on what we can configure, see +[here](https://docs.railway.app/reference/config-as-code#configurable-settings). + +## Contributing + +Please see our [contributing guide](./CONTRIBUTING.md)! 👋 diff --git a/apps/admin-dashboard/.env.example b/apps/admin-dashboard/.env.example new file mode 100644 index 000000000..0bdadeff6 --- /dev/null +++ b/apps/admin-dashboard/.env.example @@ -0,0 +1,14 @@ +# Required to run the Admin Dashboard in development... + +ADMIN_DASHBOARD_URL=http://localhost:3001 +API_URL=http://localhost:8080 +DATABASE_URL=postgresql://localhost:5432/colorstack +ENVIRONMENT=development +JWT_SECRET=_ +REDIS_URL=redis://localhost:6379 +SESSION_SECRET=_ + +# Optional for development, but won't be able to run certain features... + +# GOOGLE_CLIENT_ID= +# SENTRY_DSN= \ No newline at end of file diff --git a/apps/admin-dashboard/.eslintrc.js b/apps/admin-dashboard/.eslintrc.js new file mode 100644 index 000000000..379766a7e --- /dev/null +++ b/apps/admin-dashboard/.eslintrc.js @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: ['colorstack'], +}; diff --git a/apps/admin-dashboard/app/entry.client.tsx b/apps/admin-dashboard/app/entry.client.tsx new file mode 100644 index 000000000..1f635d147 --- /dev/null +++ b/apps/admin-dashboard/app/entry.client.tsx @@ -0,0 +1,29 @@ +import { RemixBrowser, useLocation, useMatches } from '@remix-run/react'; +import * as Sentry from '@sentry/remix'; +import { StrictMode, startTransition, useEffect } from 'react'; +import { hydrateRoot } from 'react-dom/client'; + +Sentry.init({ + dsn: window.env.SENTRY_DSN, + enabled: window.env.ENVIRONMENT !== 'development', + environment: window.env.ENVIRONMENT, + tracesSampleRate: 0.25, + integrations: [ + new Sentry.BrowserTracing({ + routingInstrumentation: Sentry.remixRouterInstrumentation( + useEffect, + useLocation, + useMatches + ), + }), + ], +}); + +startTransition(() => { + hydrateRoot( + document, + + + + ); +}); diff --git a/apps/admin-dashboard/app/entry.server.tsx b/apps/admin-dashboard/app/entry.server.tsx new file mode 100644 index 000000000..1a4cdc1ab --- /dev/null +++ b/apps/admin-dashboard/app/entry.server.tsx @@ -0,0 +1,168 @@ +import type { EntryContext } from '@remix-run/node'; +import { createReadableStreamFromReadable } from '@remix-run/node'; +import { RemixServer } from '@remix-run/react'; +import * as Sentry from '@sentry/remix'; +import dayjs from 'dayjs'; +import timezone from 'dayjs/plugin/timezone.js'; +import utc from 'dayjs/plugin/utc.js'; +import isbot from 'isbot'; +import { renderToPipeableStream } from 'react-dom/server'; +import { PassThrough } from 'stream'; + +import { getCookie } from '@colorstack/utils'; + +// Importing this file ensures that our application has all of the environment +// variables necessary to run. If any are missing, this file will throw an error +// and crash the application. +import { ENV } from './shared/constants.server'; + +dayjs.extend(utc); +dayjs.extend(timezone); + +Sentry.init({ + dsn: ENV.SENTRY_DSN, + enabled: ENV.ENVIRONMENT !== 'development', + environment: ENV.ENVIRONMENT, + tracesSampleRate: 0.25, +}); + +const ABORT_DELAY = 5000; + +export default function handleRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext +) { + const bot: boolean = isbot(request.headers.get('user-agent')); + + return bot + ? handleBotRequest( + request, + responseStatusCode, + responseHeaders, + remixContext + ) + : handleBrowserRequest( + request, + responseStatusCode, + responseHeaders, + remixContext + ); +} + +function handleBotRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext +) { + return new Promise((resolve, reject) => { + let didError = false; + + const { pipe, abort } = renderToPipeableStream( + , + { + onAllReady: () => { + const body = new PassThrough(); + + responseHeaders.set('Content-Type', 'text/html'); + + resolve( + new Response(createReadableStreamFromReadable(body), { + headers: responseHeaders, + status: didError ? 500 : responseStatusCode, + }) + ); + + pipe(body); + }, + onShellError: (error: unknown) => { + reject(error); + }, + onError: (error: unknown) => { + didError = true; + + console.error(error); + }, + } + ); + + setTimeout(abort, ABORT_DELAY); + }); +} + +function handleBrowserRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext +) { + return new Promise((resolve, reject) => { + let didError = false; + + const { pipe, abort } = renderToPipeableStream( + , + { + onShellReady: () => { + const cookie = request.headers.get('Cookie'); + + const timezone = getCookie(cookie || '', 'timezone'); + + // @see https://www.jacobparis.com/content/remix-ssr-dates + // In order to match the timezone of dates on both the client and + // the server, we need to get the timezone from the client. How we're + // doing this: if that timezone cookie value isn't present, then we're + // setting a cookie with the timezone on the client and reloading the + // page. + if (!timezone) { + return resolve( + new Response( + ` + + + + + + `, + { + headers: { + 'Content-Type': 'text/html', + 'Set-Cookie': 'timezone=America/New_York; path=/', + Refresh: `0; url=${request.url}`, + }, + } + ) + ); + } + + const body = new PassThrough(); + + responseHeaders.set('Content-Type', 'text/html'); + + resolve( + new Response(createReadableStreamFromReadable(body), { + headers: responseHeaders, + status: didError ? 500 : responseStatusCode, + }) + ); + + pipe(body); + }, + onShellError: (error: unknown) => { + reject(error); + }, + onError: (error: unknown) => { + didError = true; + + console.error(error); + }, + } + ); + + setTimeout(abort, ABORT_DELAY); + }); +} diff --git a/apps/admin-dashboard/app/root.tsx b/apps/admin-dashboard/app/root.tsx new file mode 100644 index 000000000..7ea236fc6 --- /dev/null +++ b/apps/admin-dashboard/app/root.tsx @@ -0,0 +1,85 @@ +import type { LinksFunction, MetaFunction } from '@remix-run/node'; +import { json, LoaderFunctionArgs } from '@remix-run/node'; +import { + Links, + Meta, + Outlet, + Scripts, + ScrollRestoration, + useLoaderData, +} from '@remix-run/react'; +import { withSentry } from '@sentry/remix'; + +import { Toast } from '@colorstack/core-ui'; + +import coreUiStylesheet from '@colorstack/core-ui/dist/index.css?url'; +import tailwindStylesheet from './tailwind.css?url'; + +import { ENV } from './shared/constants.server'; +import { commitSession, getSession, SESSION } from './shared/session.server'; + +export const links: LinksFunction = () => { + return [ + { rel: 'stylesheet', href: coreUiStylesheet }, + { rel: 'stylesheet', href: tailwindStylesheet }, + ]; +}; + +export const meta: MetaFunction = () => { + return [{ title: 'ColorStack | Admin Dashboard' }]; +}; + +export async function loader({ request }: LoaderFunctionArgs) { + const session = await getSession(request); + + const toast = session.get(SESSION.TOAST); + + const env: Window['env'] = { + ENVIRONMENT: ENV.ENVIRONMENT, + SENTRY_DSN: ENV.SENTRY_DSN, + }; + + return json( + { + env, + toast: toast || null, + }, + { + headers: { + 'Set-Cookie': await commitSession(session), + }, + } + ); +} + +function App() { + const { env, toast } = useLoaderData(); + + return ( + + + + + + + + + + + {toast && } + + + + + `, + { + headers: { + 'Content-Type': 'text/html', + 'Set-Cookie': 'timezone=America/New_York; path=/', + Refresh: `0; url=${request.url}`, + }, + } + ) + ); + } + + const body = new PassThrough(); + + responseHeaders.set('Content-Type', 'text/html'); + + resolve( + new Response(createReadableStreamFromReadable(body), { + headers: responseHeaders, + status: didError ? 500 : responseStatusCode, + }) + ); + + pipe(body); + }, + onShellError: (error: unknown) => { + reject(error); + }, + onError: (error: unknown) => { + didError = true; + + console.error(error); + }, + } + ); + + setTimeout(abort, ABORT_DELAY); + }); +} diff --git a/apps/member-profile/app/root.tsx b/apps/member-profile/app/root.tsx new file mode 100644 index 000000000..0f9e29b29 --- /dev/null +++ b/apps/member-profile/app/root.tsx @@ -0,0 +1,91 @@ +import type { LinksFunction, MetaFunction } from '@remix-run/node'; +import { json, LoaderFunctionArgs } from '@remix-run/node'; +import { + Links, + Meta, + Outlet, + Scripts, + ScrollRestoration, + useLoaderData, +} from '@remix-run/react'; +import { withSentry } from '@sentry/remix'; +import dayjs from 'dayjs'; +import timezone from 'dayjs/plugin/timezone.js'; +import utc from 'dayjs/plugin/utc.js'; + +import { Toast } from '@colorstack/core-ui'; + +import coreUiStylesheet from '@colorstack/core-ui/dist/index.css?url'; +import tailwindStylesheet from './tailwind.css?url'; + +import { ENV } from './shared/constants.server'; +import { commitSession, getSession, SESSION } from './shared/session.server'; + +dayjs.extend(utc); +dayjs.extend(timezone); + +export const links: LinksFunction = () => { + return [ + { rel: 'stylesheet', href: coreUiStylesheet }, + { rel: 'stylesheet', href: tailwindStylesheet }, + ]; +}; + +export const meta: MetaFunction = () => { + return [{ title: 'ColorStack | Member Profile' }]; +}; + +export async function loader({ request }: LoaderFunctionArgs) { + const session = await getSession(request); + + const toast = session.get(SESSION.TOAST); + + const env: Window['env'] = { + ENVIRONMENT: ENV.ENVIRONMENT, + SENTRY_DSN: ENV.SENTRY_DSN, + }; + + return json( + { + env, + toast: toast || null, + }, + { + headers: { + 'Set-Cookie': await commitSession(session), + }, + } + ); +} + +function App() { + const { env, toast } = useLoaderData(); + + return ( + + + + + + + + + + + {toast && } + +