Skip to content

Commit

Permalink
Merge pull request #265 from shmbajaj/feat/login-widget
Browse files Browse the repository at this point in the history
Feat/login widget
  • Loading branch information
moonlightnexus authored Feb 4, 2024
2 parents 719e4f2 + 83a757b commit 7d57265
Show file tree
Hide file tree
Showing 11 changed files with 448 additions and 11 deletions.
158 changes: 158 additions & 0 deletions src/app/widget/login/components/EmailWidget.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import React from 'react';
import { Button } from '@/components/ui/Button';
import { Input } from '@/components/ui/Input';
import {
Card,
CardContent,
CardFooter,
CardHeader
} from '@/components/ui/card';
import { getSocialLoginUrl } from '@/lib/utils';
import { useOrgData } from '../widgetStore';
import { ToastProps } from '@/components/ui/toast';
import { useToast } from '@/components/ui/use-toast';
import {
SocialLoginCollection,
SocialLoginLabel,
SocialLoginValue
} from '@/types/social-logins';
import { Icons } from './icons';
import { SocialLogin } from './SocialLogin';
import { allSocialLogins } from './data';
import { $TsFixMe } from '@/types';
import { LoginMethodSeparator } from './LoginMethodSeparator';
import Link from 'next/link';
import Image from 'next/image';

interface EmailWidgetProps {
email: string;
setEmail: (NewPass: string) => void;
loading: boolean;
handleSubmit: (e: { preventDefault: () => void }) => Promise<void>;
}

const initiateSocialLogin = async (
social: string,
orgToken: string,
toast?: (props: ToastProps) => void
): Promise<void> => {
try {
const url = await getSocialLoginUrl({ provider: social, orgToken });
window.location.href = url;
} catch (error: $TsFixMe) {
const message = `Social Login Failed: ${
error?.message ?? 'Something Went Wrong'
}`;
toast?.({
variant: 'destructive',
title: message
});
}
};

// TODO: test email-login and social-login flow
export function EmailWidget({
handleSubmit,
email,
setEmail,
loading
}: EmailWidgetProps) {
const { toast } = useToast();
const orangizationData = useOrgData(state => state.data);
const organizationToken = useOrgData(state => state.org_token);

const organizationLogoURL = orangizationData.widget.logo_url;
const organizationName = orangizationData.widget.name;

//INFO: using filter because of lack of config typesaftey and data
const allowedSocialLogins = Object.keys(orangizationData.social)
.map(e => allSocialLogins[e as SocialLoginValue])
.filter(e => e);
const isLoginWithEmailEnabled = orangizationData.email_val;
return (
<Card className="border-none shadow-none bg-transparent">
<CardHeader className="p-0 pb-4">
<Image
src={organizationLogoURL}
alt={'logo'}
height={40}
width={40}
className="w-auto h-11 object-left object-contain"
/>
</CardHeader>
<CardContent className="space-y-6 p-0 pb-4">
<div className="text-left">
<h2 className="font-semibold text-xl">Sign in</h2>
<p className="font-medium text-base text-muted-foreground">
to continue to{' '}
<strong className="text-black">{organizationName}</strong>
</p>
</div>
<div className="space-y-4">
{allowedSocialLogins.map(item => {
const Icon = Icons[item.icon];
return (
<SocialLogin
key={item.value}
onClick={() =>
initiateSocialLogin(item.value, organizationToken, toast)
}
>
<Icon className="h-5 w-5" />
<span>Continue with {item.label}</span>
</SocialLogin>
);
})}
</div>
{isLoginWithEmailEnabled && (
<>
<LoginMethodSeparator />
<form className="space-y-2" onSubmit={handleSubmit}>
<label
htmlFor="email"
className="block text-xs leading-5 font-medium text-gray-700"
>
Email address
</label>
<Input
id="email"
type="email"
name="email"
className="w-full"
value={email}
onChange={e => setEmail(e.target.value)}
required
/>
<Button
className="w-full bg-login hover:bg-login/90 text-white font-semibold text-[10px] leading-tight"
disabled={loading}
>
CONTINUE
</Button>
</form>
</>
)}
</CardContent>
{/* Not handling pp and tnc because no response type available, `unknown` cannot be used.
Ref: https://github.com/One-Click-Auth/auth_frontend/pull/265#issuecomment-1912395385
*/}
<CardFooter className="p-0 pb-4">
<p className="text-[10px] text-[#000000A6] leading-4">
By proceeding, I acknowledge and agree to abide by the terms outlined
in the&nbsp;
<Link href="#">
<strong className="text-login hover:text-login/85">
Privacy Policy
</strong>
</Link>
&nbsp;and{' '}
<Link href="#">
<strong className="text-login hover:text-login/85">
Terms &amp; Conditions.
</strong>
</Link>
</p>
</CardFooter>
</Card>
);
}
11 changes: 11 additions & 0 deletions src/app/widget/login/components/LoginMethodSeparator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Separator } from '@/components/ui/seperator';

export function LoginMethodSeparator() {
return (
<div className="grid grid-cols-[1fr_0.5fr_1fr] place-items-center">
<Separator />
<span>or</span>
<Separator />
</div>
);
}
15 changes: 15 additions & 0 deletions src/app/widget/login/components/SocialLogin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Button } from '@/components/ui/Button';

export function SocialLogin({
onClick,
...props
}: React.HTMLAttributes<HTMLButtonElement>) {
return (
<Button
className="w-full gap-2 text-left items-center justify-start hover:bg-secondary font-normal text-xs leading-4"
variant="outline"
onClick={onClick}
{...props}
/>
);
}
33 changes: 33 additions & 0 deletions src/app/widget/login/components/data.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {
SocialLoginCollection,
SocialLoginLabel,
SocialLoginValue
} from '@/types/social-logins';

export const allSocialLogins: SocialLoginCollection = {
[SocialLoginValue.Github]: {
icon: 'github',
label: SocialLoginLabel.Github,
value: SocialLoginValue.Github
},
[SocialLoginValue.Google]: {
icon: 'google',
label: SocialLoginLabel.Google,
value: SocialLoginValue.Google
},
[SocialLoginValue.Discord]: {
icon: 'discord',
label: SocialLoginLabel.Discord,
value: SocialLoginValue.Discord
},
[SocialLoginValue.Figma]: {
icon: 'figma',
label: SocialLoginLabel.Figma,
value: SocialLoginValue.Figma
},
[SocialLoginValue.Microsoft]: {
icon: 'microsoft',
label: SocialLoginLabel.Microsoft,
value: SocialLoginValue.Microsoft
}
};
139 changes: 139 additions & 0 deletions src/app/widget/login/components/icons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
type IconProps = React.HTMLAttributes<SVGElement>;

export const Icons = {
microsoft: (props: IconProps) => (
<svg
width="31"
height="34"
viewBox="0 0 31 34"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M14.7957 16.0851H0.223145V0.137695H14.7957V16.0851Z"
fill="#F1511B"
/>
<path
d="M30.6433 16.0851H15.7957V0.137695H30.6394V16.0851H30.6433Z"
fill="#80CC28"
/>
<path
d="M14.7957 33.0323H0.223145V17.085H14.7957V33.0323Z"
fill="#00ADEF"
/>
<path
d="M30.6433 33.0323H15.7957V17.085H30.6394V33.0323H30.6433Z"
fill="#FBBC09"
/>
</svg>
),
discord: (props: IconProps) => (
<svg
width="800px"
height="800px"
viewBox="0 -28.5 256 256"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
// xmlns:xlink="http://www.w3.org/1999/xlink"
preserveAspectRatio="xMidYMid"
{...props}
>
<g>
<path
d="M216.856339,16.5966031 C200.285002,8.84328665 182.566144,3.2084988 164.041564,0 C161.766523,4.11318106 159.108624,9.64549908 157.276099,14.0464379 C137.583995,11.0849896 118.072967,11.0849896 98.7430163,14.0464379 C96.9108417,9.64549908 94.1925838,4.11318106 91.8971895,0 C73.3526068,3.2084988 55.6133949,8.86399117 39.0420583,16.6376612 C5.61752293,67.146514 -3.4433191,116.400813 1.08711069,164.955721 C23.2560196,181.510915 44.7403634,191.567697 65.8621325,198.148576 C71.0772151,190.971126 75.7283628,183.341335 79.7352139,175.300261 C72.104019,172.400575 64.7949724,168.822202 57.8887866,164.667963 C59.7209612,163.310589 61.5131304,161.891452 63.2445898,160.431257 C105.36741,180.133187 151.134928,180.133187 192.754523,160.431257 C194.506336,161.891452 196.298154,163.310589 198.110326,164.667963 C191.183787,168.842556 183.854737,172.420929 176.223542,175.320965 C180.230393,183.341335 184.861538,190.991831 190.096624,198.16893 C211.238746,191.588051 232.743023,181.531619 254.911949,164.955721 C260.227747,108.668201 245.831087,59.8662432 216.856339,16.5966031 Z M85.4738752,135.09489 C72.8290281,135.09489 62.4592217,123.290155 62.4592217,108.914901 C62.4592217,94.5396472 72.607595,82.7145587 85.4738752,82.7145587 C98.3405064,82.7145587 108.709962,94.5189427 108.488529,108.914901 C108.508531,123.290155 98.3405064,135.09489 85.4738752,135.09489 Z M170.525237,135.09489 C157.88039,135.09489 147.510584,123.290155 147.510584,108.914901 C147.510584,94.5396472 157.658606,82.7145587 170.525237,82.7145587 C183.391518,82.7145587 193.761324,94.5189427 193.539891,108.914901 C193.539891,123.290155 183.391518,135.09489 170.525237,135.09489 Z"
fill="#5865F2"
fill-rule="nonzero"
></path>
</g>
</svg>
),
figma: (props: IconProps) => (
<svg
width="38"
height="57"
viewBox="0 0 38 57"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<g id="figma_logo" clip-path="url(#clip0_1_137)">
<path
id="Vector"
d="M19 28.5C19 25.9804 20.0009 23.5641 21.7825 21.7825C23.5641 20.0009 25.9804 19 28.5 19C31.0196 19 33.4359 20.0009 35.2175 21.7825C36.9991 23.5641 38 25.9804 38 28.5C38 31.0196 36.9991 33.4359 35.2175 35.2175C33.4359 36.9991 31.0196 38 28.5 38C25.9804 38 23.5641 36.9991 21.7825 35.2175C20.0009 33.4359 19 31.0196 19 28.5Z"
fill="#1ABCFE"
/>
<path
id="Vector_2"
d="M0 47.5C0 44.9804 1.00089 42.5641 2.78249 40.7825C4.56408 39.0009 6.98044 38 9.5 38H19V47.5C19 50.0196 17.9991 52.4359 16.2175 54.2175C14.4359 55.9991 12.0196 57 9.5 57C6.98044 57 4.56408 55.9991 2.78249 54.2175C1.00089 52.4359 0 50.0196 0 47.5H0Z"
fill="#0ACF83"
/>
<path
id="Vector_3"
d="M19 0V19H28.5C31.0196 19 33.4359 17.9991 35.2175 16.2175C36.9991 14.4359 38 12.0196 38 9.5C38 6.98044 36.9991 4.56408 35.2175 2.78249C33.4359 1.00089 31.0196 0 28.5 0L19 0Z"
fill="#FF7262"
/>
<path
id="Vector_4"
d="M0 9.5C0 12.0196 1.00089 14.4359 2.78249 16.2175C4.56408 17.9991 6.98044 19 9.5 19H19V0H9.5C6.98044 0 4.56408 1.00089 2.78249 2.78249C1.00089 4.56408 0 6.98044 0 9.5H0Z"
fill="#F24E1E"
/>
<path
id="Vector_5"
d="M0 28.5C0 31.0196 1.00089 33.4359 2.78249 35.2175C4.56408 36.9991 6.98044 38 9.5 38H19V19H9.5C6.98044 19 4.56408 20.0009 2.78249 21.7825C1.00089 23.5641 0 25.9804 0 28.5H0Z"
fill="#A259FF"
/>
</g>
<defs>
<clipPath id="clip0_1_137">
<rect width="38" height="57" fill="white" />
</clipPath>
</defs>
</svg>
),
github: (props: IconProps) => (
<svg viewBox="0 0 438.549 438.549" {...props}>
<path
fill="currentColor"
d="M409.132 114.573c-19.608-33.596-46.205-60.194-79.798-79.8-33.598-19.607-70.277-29.408-110.063-29.408-39.781 0-76.472 9.804-110.063 29.408-33.596 19.605-60.192 46.204-79.8 79.8C9.803 148.168 0 184.854 0 224.63c0 47.78 13.94 90.745 41.827 128.906 27.884 38.164 63.906 64.572 108.063 79.227 5.14.954 8.945.283 11.419-1.996 2.475-2.282 3.711-5.14 3.711-8.562 0-.571-.049-5.708-.144-15.417a2549.81 2549.81 0 01-.144-25.406l-6.567 1.136c-4.187.767-9.469 1.092-15.846 1-6.374-.089-12.991-.757-19.842-1.999-6.854-1.231-13.229-4.086-19.13-8.559-5.898-4.473-10.085-10.328-12.56-17.556l-2.855-6.57c-1.903-4.374-4.899-9.233-8.992-14.559-4.093-5.331-8.232-8.945-12.419-10.848l-1.999-1.431c-1.332-.951-2.568-2.098-3.711-3.429-1.142-1.331-1.997-2.663-2.568-3.997-.572-1.335-.098-2.43 1.427-3.289 1.525-.859 4.281-1.276 8.28-1.276l5.708.853c3.807.763 8.516 3.042 14.133 6.851 5.614 3.806 10.229 8.754 13.846 14.842 4.38 7.806 9.657 13.754 15.846 17.847 6.184 4.093 12.419 6.136 18.699 6.136 6.28 0 11.704-.476 16.274-1.423 4.565-.952 8.848-2.383 12.847-4.285 1.713-12.758 6.377-22.559 13.988-29.41-10.848-1.14-20.601-2.857-29.264-5.14-8.658-2.286-17.605-5.996-26.835-11.14-9.235-5.137-16.896-11.516-22.985-19.126-6.09-7.614-11.088-17.61-14.987-29.979-3.901-12.374-5.852-26.648-5.852-42.826 0-23.035 7.52-42.637 22.557-58.817-7.044-17.318-6.379-36.732 1.997-58.24 5.52-1.715 13.706-.428 24.554 3.853 10.85 4.283 18.794 7.952 23.84 10.994 5.046 3.041 9.089 5.618 12.135 7.708 17.705-4.947 35.976-7.421 54.818-7.421s37.117 2.474 54.823 7.421l10.849-6.849c7.419-4.57 16.18-8.758 26.262-12.565 10.088-3.805 17.802-4.853 23.134-3.138 8.562 21.509 9.325 40.922 2.279 58.24 15.036 16.18 22.559 35.787 22.559 58.817 0 16.178-1.958 30.497-5.853 42.966-3.9 12.471-8.941 22.457-15.125 29.979-6.191 7.521-13.901 13.85-23.131 18.986-9.232 5.14-18.182 8.85-26.84 11.136-8.662 2.286-18.415 4.004-29.263 5.146 9.894 8.562 14.842 22.077 14.842 40.539v60.237c0 3.422 1.19 6.279 3.572 8.562 2.379 2.279 6.136 2.95 11.276 1.995 44.163-14.653 80.185-41.062 108.068-79.226 27.88-38.161 41.825-81.126 41.825-128.906-.01-39.771-9.818-76.454-29.414-110.049z"
></path>
</svg>
),
google: (props: IconProps) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="705.6"
height="720"
viewBox="0 0 186.69 190.5"
// xmlns:v="https://vecta.io/nano"
{...props}
>
<g transform="translate(1184.583 765.171)">
<path
clip-path="none"
mask="none"
d="M-1089.333-687.239v36.888h51.262c-2.251 11.863-9.006 21.908-19.137 28.662l30.913 23.986c18.011-16.625 28.402-41.044 28.402-70.052 0-6.754-.606-13.249-1.732-19.483z"
fill="#4285f4"
/>
<path
clip-path="none"
mask="none"
d="M-1142.714-651.791l-6.972 5.337-24.679 19.223h0c15.673 31.086 47.796 52.561 85.03 52.561 25.717 0 47.278-8.486 63.038-23.033l-30.913-23.986c-8.486 5.715-19.31 9.179-32.125 9.179-24.765 0-45.806-16.712-53.34-39.226z"
fill="#34a853"
/>
<path
clip-path="none"
mask="none"
d="M-1174.365-712.61c-6.494 12.815-10.217 27.276-10.217 42.689s3.723 29.874 10.217 42.689c0 .086 31.693-24.592 31.693-24.592-1.905-5.715-3.031-11.776-3.031-18.098s1.126-12.383 3.031-18.098z"
fill="#fbbc05"
/>
<path
d="M-1089.333-727.244c14.028 0 26.497 4.849 36.455 14.201l27.276-27.276c-16.539-15.413-38.013-24.852-63.731-24.852-37.234 0-69.359 21.388-85.032 52.561l31.692 24.592c7.533-22.514 28.575-39.226 53.34-39.226z"
fill="#ea4335"
clip-path="none"
mask="none"
/>
</g>
</svg>
)
};
Loading

0 comments on commit 7d57265

Please sign in to comment.