✨ feat: add oauth button
This commit is contained in:
@ -123,4 +123,4 @@
|
|||||||
body {
|
body {
|
||||||
@apply bg-background text-foreground;
|
@apply bg-background text-foreground;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
5
bun.lock
5
bun.lock
@ -6,6 +6,7 @@
|
|||||||
"name": "frontend",
|
"name": "frontend",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@base-ui/react": "^1.0.0",
|
"@base-ui/react": "^1.0.0",
|
||||||
|
"@iconify/react": "^6.0.2",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"lucide-react": "^0.562.0",
|
"lucide-react": "^0.562.0",
|
||||||
@ -147,6 +148,10 @@
|
|||||||
|
|
||||||
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
|
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
|
||||||
|
|
||||||
|
"@iconify/react": ["@iconify/react@6.0.2", "", { "dependencies": { "@iconify/types": "^2.0.0" }, "peerDependencies": { "react": ">=16" } }, "sha512-SMmC2sactfpJD427WJEDN6PMyznTFMhByK9yLW0gOTtnjzzbsi/Ke/XqsumsavFPwNiXs8jSiYeZTmLCLwO+Fg=="],
|
||||||
|
|
||||||
|
"@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="],
|
||||||
|
|
||||||
"@img/colour": ["@img/colour@1.0.0", "", {}, "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw=="],
|
"@img/colour": ["@img/colour@1.0.0", "", {}, "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw=="],
|
||||||
|
|
||||||
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="],
|
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="],
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@base-ui/react": "^1.0.0",
|
"@base-ui/react": "^1.0.0",
|
||||||
|
"@iconify/react": "^6.0.2",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"lucide-react": "^0.562.0",
|
"lucide-react": "^0.562.0",
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
interface BackendResponse<T = unknown> {
|
export interface BackendResponse<T = unknown> {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
message: string;
|
message: string;
|
||||||
data?: T;
|
data?: T;
|
||||||
|
|||||||
@ -33,6 +33,9 @@ const buttonVariants = cva(
|
|||||||
"size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
|
"size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
|
||||||
"icon-lg": "size-9",
|
"icon-lg": "size-9",
|
||||||
},
|
},
|
||||||
|
isDisabled: {
|
||||||
|
true: "bg-neutral-800 text-neutral-400 cursor-not-allowed text-xs",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
variant: "default",
|
variant: "default",
|
||||||
@ -46,10 +49,12 @@ function Button({
|
|||||||
variant = "default",
|
variant = "default",
|
||||||
size = "default",
|
size = "default",
|
||||||
asChild = false,
|
asChild = false,
|
||||||
|
isDisabled = false,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"button"> &
|
}: React.ComponentProps<"button"> &
|
||||||
VariantProps<typeof buttonVariants> & {
|
VariantProps<typeof buttonVariants> & {
|
||||||
asChild?: boolean;
|
asChild?: boolean;
|
||||||
|
isDisabled?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const Comp = asChild ? Slot.Root : "button";
|
const Comp = asChild ? Slot.Root : "button";
|
||||||
|
|
||||||
@ -58,7 +63,7 @@ function Button({
|
|||||||
data-slot="button"
|
data-slot="button"
|
||||||
data-variant={variant}
|
data-variant={variant}
|
||||||
data-size={size}
|
data-size={size}
|
||||||
className={cn(buttonVariants({ variant, size, className }))}
|
className={cn(buttonVariants({ variant, size, isDisabled, className }))}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
14
shared/widgets/signin/actions/getAllThirdPartyAuth.ts
Normal file
14
shared/widgets/signin/actions/getAllThirdPartyAuth.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
"use server";
|
||||||
|
import { backendFetch, BackendResponse } from "@/shared/helper/backendFetch";
|
||||||
|
|
||||||
|
export type GetALlThirdPartyAuthCallback = BackendResponse<
|
||||||
|
{
|
||||||
|
name: string;
|
||||||
|
icon: string;
|
||||||
|
req_endpoint: string;
|
||||||
|
}[]
|
||||||
|
>;
|
||||||
|
|
||||||
|
export const getAllThirdPartyAuth = async () => {
|
||||||
|
return (await backendFetch("auth/providers")) as GetALlThirdPartyAuthCallback;
|
||||||
|
};
|
||||||
@ -10,8 +10,25 @@ import {
|
|||||||
import { Input } from "@/shared/libs/shadcn/ui/input";
|
import { Input } from "@/shared/libs/shadcn/ui/input";
|
||||||
import { Label } from "@/shared/libs/shadcn/ui/label";
|
import { Label } from "@/shared/libs/shadcn/ui/label";
|
||||||
import { Separator } from "@/shared/libs/shadcn/ui/separator";
|
import { Separator } from "@/shared/libs/shadcn/ui/separator";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import {
|
||||||
|
getAllThirdPartyAuth,
|
||||||
|
GetALlThirdPartyAuthCallback,
|
||||||
|
} from "../actions/getAllThirdPartyAuth";
|
||||||
|
import { Icon } from "@iconify/react";
|
||||||
|
|
||||||
const SignInCard = () => {
|
const SignInCard = () => {
|
||||||
|
const [oAuthProviders, setOAuthProviders] =
|
||||||
|
useState<GetALlThirdPartyAuthCallback | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
const res = await getAllThirdPartyAuth();
|
||||||
|
console.log(res);
|
||||||
|
setOAuthProviders(res);
|
||||||
|
})();
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DialogContent showCloseButton={false}>
|
<DialogContent showCloseButton={false}>
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
@ -26,6 +43,31 @@ const SignInCard = () => {
|
|||||||
<Label htmlFor="email">Email</Label>
|
<Label htmlFor="email">Email</Label>
|
||||||
<Input type="email" id="email" placeholder="e.g. user@example.com" />
|
<Input type="email" id="email" placeholder="e.g. user@example.com" />
|
||||||
</div>
|
</div>
|
||||||
|
<div className="my-4 flex items-center gap-2 ">
|
||||||
|
<Separator className="flex-1 bg-neutral-700" />
|
||||||
|
<p className="text-neutral-500 text-sm">or continue with</p>
|
||||||
|
<Separator className="flex-1 bg-neutral-700" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{oAuthProviders ? (
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
{oAuthProviders.data?.map((provider, index) => (
|
||||||
|
<Button
|
||||||
|
key={index}
|
||||||
|
variant="outline"
|
||||||
|
className="w-full text-neutral-300 text-xs font-normal"
|
||||||
|
>
|
||||||
|
<Icon icon={provider.icon} />
|
||||||
|
Continue with {provider.name}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<Button size="sm" className="w-full" isDisabled>
|
||||||
|
There are no third-party auth providers available.
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
<DialogClose asChild>
|
<DialogClose asChild>
|
||||||
|
|||||||
Reference in New Issue
Block a user