Skip to content

feat: add institution route and membership grant component #2956

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<div
class="flex flex-col items-center gap-y-6 bg-teal-50/25 dark:bg-teal-800/40 border-teal-500 dark:border-teal-600 px-4 py-12 border rounded-md shadow-xl"
...attributes
>
<div class="flex items-center justify-center gap-2">
<img alt="avatar" src="https://www.nus.edu.sg/images/default-source/identity-images/NUS_logo_full-vertical.jpg" class="h-20" />

{{svg-jar "plus" class="w-10 h-10 text-gray-600 dark:text-gray-400 opacity-90 group-hover:opacity-100 transition-all"}}

<img class="h-14" src={{this.logoImage}} alt="CodeCrafters" />
</div>

<div class="prose dark:prose-invert text-center max-w-sm">
<p>
Students, alumni and staff at
<b class="dark:text-gray-50">NUS</b>
get
<b class="dark:text-gray-50">1 year</b>
of CodeCrafters for free.
</p>
</div>

<div class="flex flex-col items-center">
{{! Disabled buttons can be translucent, the added background makes them more visible }}
<div class="inline-flex bg-white dark:bg-gray-850 rounded-sm">
<AffiliateLinkPage::AcceptReferralButton @affiliateLink={{@affiliateLink}} @course={{@course}} />
</div>

<div class="text-gray-500 dark:text-gray-400 text-xs mt-3">
No credit card required.
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import Component from '@glimmer/component';
import logoImage from '/assets/images/logo/logomark-color.svg';

interface Signature {
Element: HTMLDivElement;
}

export default class CreateMembershipGrantApplicationContainerComponent extends Component<Signature> {
logoImage = logoImage;
}

declare module '@glint/environment-ember-loose/registry' {
export default interface Registry {
'InstitutionPage::CreateMembershipGrantApplicationContainer': typeof CreateMembershipGrantApplicationContainerComponent;
}
}
90 changes: 90 additions & 0 deletions app/controllers/institution.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import BYOXBanner from '/assets/images/affiliate-program-features/byox-banner.svg';
import BYOXBannerMobile from '/assets/images/affiliate-program-features/byox-banner-mobile.svg';
import Controller from '@ember/controller';
import amazonImage from '/assets/images/company-logos/amazon-company-logo.svg';
import appleImage from '/assets/images/company-logos/apple-company-logo.svg';
import coinbaseImage from '/assets/images/company-logos/coinbase-company-logo.svg';
import figmaImage from '/assets/images/company-logos/figma-company-logo.svg';
import googleImage from '/assets/images/company-logos/google-company-logo.svg';
import harvardImage from '/assets/images/company-logos/harvard-logo.svg';
import hashiCorpImage from '/assets/images/company-logos/hashicorp-company-logo.svg';
import mitImage from '/assets/images/company-logos/mit-logo.svg';
import slackImage from '/assets/images/company-logos/slack-company-logo.svg';
import stripeImage from '/assets/images/company-logos/stripe-company-logo.svg';
import testimonialsData from 'codecrafters-frontend/utils/testimonials-data';
import type { Testimonial } from 'codecrafters-frontend/utils/testimonials-data';

export default class InstitutionController extends Controller {
BYOXBanner = BYOXBanner;
BYOXBannerMobile = BYOXBannerMobile;

get companies() {
return [
{
name: 'Google',
url: googleImage,
},
{
name: 'Slack',
url: slackImage,
},
{
name: 'Amazon',
url: amazonImage,
},
{
name: 'Figma',
url: figmaImage,
},
{
name: 'Stripe',
url: stripeImage,
},
{
name: 'Apple',
url: appleImage,
},
{
name: 'Coinbase',
url: coinbaseImage,
},
{
name: 'HashiCorp',
url: hashiCorpImage,
},
{
name: 'Harvard',
url: harvardImage,
},
{
name: 'MIT',
url: mitImage,
},
];
}

get testimonialGroups(): Testimonial[][] {
const testimonialGroup1 = [
testimonialsData['djordje-lukic']!,
testimonialsData['ananthalakshmi-sankar']!,
testimonialsData['raghav-dua']!,
testimonialsData['rahul-tarak']!,
];

const testimonialGroup2 = [
testimonialsData['charles-guo']!,
testimonialsData['akshata-mohan']!,
testimonialsData['pranjal-paliwal']!,
testimonialsData['beyang-liu']!,
];

const testimonialGroup3 = [
testimonialsData['beyang-liu']!,
testimonialsData['kang-ming-tay']!,
testimonialsData['jonathan-lorimer']!,
testimonialsData['patrick-burris']!,
];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Duplicate Testimonial in Multiple Groups

The testimonial for 'beyang-liu' is duplicated in both testimonialGroup2 and testimonialGroup3 within the testimonialGroups getter. This is likely a copy-paste error, causing the same testimonial to be displayed twice on the page.

Locations (1)
Fix in Cursor Fix in Web


return [testimonialGroup1, testimonialGroup2, testimonialGroup3];
}
}
1 change: 1 addition & 0 deletions app/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ Router.map(function () {

this.route('course-overview', { path: '/courses/:course_slug/overview' }); // TODO: Add dark mode support
this.route('debug');
this.route('institution', { path: '/institutions/:institution_slug' });
this.route('join'); // TODO: Add dark mode support
this.route('join-course', { path: '/join/:course_slug' });
this.route('join-track', { path: '/join-track/:track_slug' });
Expand Down
67 changes: 67 additions & 0 deletions app/templates/institution.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{{page-title (concat "NUS offer")}}

<div class="bg-white bg-github-green-dot-wall">
<div class="container mx-auto lg:max-w-(--breakpoint-xl) pt-8 sm:pt-16 pb-48 px-3 md:px-6">
<div class="space-y-6 text-center max-w-[580px] mx-auto mb-8">
<h1 class="text-3xl text-gray-900 font-bold mb-6 md:text-4xl text-balance">
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Template Title and Logo Not Dynamic

The institution.hbs template, intended for generic institution pages, hardcodes the page title to "NUS offer" and the NUS logo URL. Both should be dynamic, based on the institution_slug parameter.

Locations (1)
Fix in Cursor Fix in Web

Become a
<span class="font-extrabold">better, confident</span>
programmer.
</h1>

<p class="text-gray-700 text-balance text-sm leading-relaxed sm:text-lg sm:leading-relaxed">
Stop letting advanced programming projects intimidate you. Start approaching them with the calm and confidence of a craftsman who has seen it
before.
</p>
</div>

<div class="flex justify-center items-center mb-20">
<InstitutionPage::CreateMembershipGrantApplicationContainer class="max-w-xs" />
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Missing Arguments Cause Undefined Values

The InstitutionPage::CreateMembershipGrantApplicationContainer component is invoked without the required @affiliateLink and @course arguments. Its template expects these arguments, which results in undefined values being passed to the nested AffiliateLinkPage::AcceptReferralButton component.

Locations (1)
Fix in Cursor Fix in Web

</div>

<div class="space-y-6 text-center mt-8 mb-8 max-w-[640px] mx-auto">
<h2 class="text-3xl md:text-4xl font-bold text-gray-900">
Trusted by senior engineers at
<span class="italic font-extrabold">the world's best companies</span>
</h2>
<p class="text-sm md:text-lg text-gray-800">
Discover how core contributors to Docker and Next.js practice writing code at the edge of their abilities — as well as senior engineers at
companies like Apple, NVIDIA, and Stripe.
</p>
</div>

<h2 class="text-gray-400 uppercase text-center text-xs mb-5">Trusted by engineers at top companies</h2>
<AffiliateLinkPage::LogoCloud />

<img src={{this.BYOXBanner}} alt="Build Your Own X GitHub Banner" class="hidden sm:block sm:w-4/5 mx-auto mt-16" />
<img src={{this.BYOXBannerMobile}} alt="Build Your Own X GitHub Banner" class="block sm:hidden w-full mt-20" />

<div class="flex flex-col gap-4 justify-center items-center mt-16">
<AffiliateLinkPage::AcceptReferralButton @affiliateLink={{this.model.affiliateLink}} />
<div class="text-xs text-slate-700 text-center">Get a free 1 year membership</div>
</div>

<h2 class="text-2xl font-bold text-gray-900 md:text-3xl text-center mt-16">
Hear it from our members
</h2>

<div class="text-gray-500 text-sm text-center mt-2">
Engineers at top teams love The CodeCrafters Way<sup>TM</sup>.
</div>

<div class="mt-12 grid grid-cols-1 md:grid-cols-3 gap-2">
{{#each this.testimonialGroups as |testimonialGroup index|}}
<div class="flex flex-col space-y-2 {{if (not-eq index 1) 'md:mt-6'}}">
{{#each testimonialGroup as |testimonial|}}
<AffiliateLinkPage::TestimonialListItem @testimonial={{testimonial}} />
{{/each}}
</div>
{{/each}}
</div>

<div class="flex flex-col gap-4 justify-center items-center mt-16">
<AffiliateLinkPage::AcceptReferralButton @affiliateLink={{this.model.affiliateLink}} />
<div class="text-xs text-slate-700 text-center">Get a free 1 year membership</div>
</div>
</div>
</div>
Loading