Skip to content

Instantly share code, notes, and snippets.

@rlindskog
Created May 1, 2020 18:37
Show Gist options
  • Save rlindskog/55a5d0ebbaaa42db3cec8b9180071f58 to your computer and use it in GitHub Desktop.
Save rlindskog/55a5d0ebbaaa42db3cec8b9180071f58 to your computer and use it in GitHub Desktop.
import React, { useRef, ChangeEvent, useCallback } from 'react';
import classNames from 'classnames';
export enum Plans {
free = 'free',
standard = 'standard',
pro = 'pro',
}
interface PlanInputRadioProps {
appsAmount: number | string;
costPerMonth: number;
planName: Plans;
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
selectedPlan: Plans;
className?: string;
}
const PlanInputRadio: React.FC<PlanInputRadioProps> = ({
planName,
onChange,
selectedPlan,
costPerMonth,
appsAmount,
className,
}) => {
const radioId = `${planName}-plan`;
return (
<>
<input
name="plan"
id={radioId}
type="radio"
className="opacity-0 absolute"
value={planName}
onChange={onChange}
checked={selectedPlan === planName}
/>
<label
htmlFor={radioId}
className={classNames(
'w-32 h-24 bg-white shadow-md cursor-pointer rounded-md hover:shadow-xl transition duration-300 mr-3 mb-3',
{
'border-indigo-600 border-2 bg-indigo-50':
selectedPlan === planName,
className,
},
)}>
<div className="mt-3 ml-3">
<h3 className="uppercase text-xs text-gray-600 font-semibold">
{planName}
</h3>
<p className="text-xs font-bold mt-1">
<span className={planName === Plans.pro ? 'text-md' : 'text-xl'}>
{appsAmount}
</span>
<span
className={classNames(
'font-medium',
planName === Plans.pro ? 'text-md' : 'text-lg',
)}>
{' '}
apps
</span>
</p>
<p className={'text-xs mt-1'}>
<span className="font-bold">${costPerMonth}</span>
<span className="font-light"> / mo</span>
</p>
</div>
</label>
</>
);
};
export const isPlan = (val: string): val is Plans => val in Plans;
interface PlanInputProps {
onChange?: (plan: Plans) => void;
value?: Plans;
className?: string;
}
const PlanInput: React.FC<PlanInputProps> = ({
onChange,
value = Plans.free,
className,
}) => {
const plans = useRef([
{ planName: Plans.free, costPerMonth: 0, appsAmount: 2 },
{ planName: Plans.standard, costPerMonth: 19, appsAmount: 10 },
{ planName: Plans.pro, costPerMonth: 29, appsAmount: 'Unlimited' },
]);
const radioChange = useCallback(
(e: ChangeEvent<HTMLInputElement>) => {
const radioValue = e.target.value;
if (radioValue && isPlan(radioValue)) {
if (onChange) {
onChange(radioValue);
}
}
},
[onChange],
);
return (
<div className="flex w-full justify-start flex-wrap mt-3">
{plans.current.map(planData => (
<PlanInputRadio
className={className}
key={planData.planName}
planName={planData.planName}
onChange={radioChange}
costPerMonth={planData.costPerMonth}
appsAmount={planData.appsAmount}
selectedPlan={value as Plans}
/>
))}
</div>
);
};
export default PlanInput;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment