- Deleted redundant components (`AddActionButton`, `AlertBox`, `AlertStack`, `BackButton`, `CancelButton`, and `CollapsableArea`) and related files. - Removed unused models (`Book`, `BookSerie`, `BookTables`, `Character`, and `Chapter`) to reduce codebase clutter. - Updated project structure and references to reflect these removals.
141 lines
5.5 KiB
TypeScript
Executable File
141 lines
5.5 KiB
TypeScript
Executable File
import React, {useContext, useEffect} from "react";
|
|
import {AlertContext} from "@/context/AlertContext";
|
|
import {configs} from "@/lib/configs";
|
|
import {useTranslations} from "@/lib/i18n";
|
|
import {LangContext, LangContextProps} from "@/context/LangContext";
|
|
import * as tauri from '@/lib/tauri';
|
|
import {apiPostPublic} from "@/lib/api/client";
|
|
|
|
const FacebookIcon = () => (
|
|
<svg className="w-6 h-6" viewBox="0 0 320 512" fill="currentColor">
|
|
<path d="M80 299.3V512H196V299.3h86.5l18-97.8H196V166.9c0-51.7 20.3-71.5 72.7-71.5c16.3 0 29.4.4 37 1.2V7.9C291.4 4 256.4 0 236.2 0C129.3 0 80 50.5 80 159.4v42.1H14v97.8H80z"/>
|
|
</svg>
|
|
);
|
|
|
|
const GoogleIcon = () => (
|
|
<svg className="w-6 h-6" viewBox="0 0 488 512" fill="currentColor">
|
|
<path d="M488 261.8C488 403.3 391.1 504 248 504 110.8 504 0 393.2 0 256S110.8 8 248 8c66.8 0 123 24.5 166.3 64.9l-67.5 64.9C258.5 52.6 94.3 116.6 94.3 256c0 86.5 69.1 156.6 153.7 156.6 98.2 0 135-70.4 140.8-106.9H248v-85.3h236.1c2.3 12.7 3.9 24.9 3.9 41.4z"/>
|
|
</svg>
|
|
);
|
|
|
|
const AppleIcon = () => (
|
|
<svg className="w-6 h-6" viewBox="0 0 384 512" fill="currentColor">
|
|
<path d="M318.7 268.7c-.2-36.7 16.4-64.4 50-84.8-18.8-26.9-47.2-41.7-84.7-44.6-35.5-2.8-74.3 20.7-88.5 20.7-15 0-49.4-19.7-76.4-19.7C63.3 141.2 4 184.8 4 273.5q0 39.3 14.4 81.2c12.8 36.7 59 126.7 107.2 125.2 25.2-.6 43-17.9 75.8-17.9 31.8 0 48.3 17.9 76.4 17.9 48.6-.7 90.4-82.5 102.6-119.3-65.2-30.7-61.7-90-61.7-91.9zm-56.6-164.2c27.3-32.4 24.8-61.9 24-72.5-24.1 1.4-52 16.4-67.9 34.9-17.5 19.8-27.8 44.3-25.6 71.9 26.1 2 49.9-11.4 69.5-34.3z"/>
|
|
</svg>
|
|
);
|
|
|
|
export default function SocialForm() {
|
|
const {errorMessage} = useContext(AlertContext);
|
|
const t = useTranslations();
|
|
const {lang} = useContext<LangContextProps>(LangContext)
|
|
|
|
useEffect((): void => {
|
|
const params = new URLSearchParams(window.location.search);
|
|
const provider: string | null = params.get('provider');
|
|
if (!provider) return;
|
|
|
|
const code: string | null = params.get('code');
|
|
if (!code) return;
|
|
|
|
if (provider === 'google') {
|
|
handleGoogleLogin(code).then();
|
|
return;
|
|
}
|
|
if (provider === 'facebook') {
|
|
const state: string | null = params.get('state');
|
|
if (!state) return;
|
|
handleFacebookLogin(code, state).then();
|
|
return;
|
|
}
|
|
if (provider === 'apple') {
|
|
const state: string | null = params.get('state');
|
|
if (!state) return;
|
|
handleAppleLogin(code, state).then();
|
|
return;
|
|
}
|
|
}, []);
|
|
|
|
async function handleLoginSuccess(token: string): Promise<void> {
|
|
await tauri.setToken(token);
|
|
await tauri.loginSuccess();
|
|
}
|
|
|
|
async function handleFacebookLogin(code: string, state: string): Promise<void> {
|
|
if (code && state) {
|
|
const response: string = await apiPostPublic<string>(`auth/facebook`, {
|
|
code: code,
|
|
state: state,
|
|
}, lang);
|
|
if (!response) {
|
|
errorMessage(t('socialForm.error.connection'));
|
|
return;
|
|
}
|
|
await handleLoginSuccess(response);
|
|
}
|
|
}
|
|
|
|
async function handleGoogleLogin(code: string): Promise<void> {
|
|
if (code) {
|
|
const response: string = await apiPostPublic<string>(`auth/google`, {
|
|
code: code,
|
|
}, lang);
|
|
if (!response) {
|
|
errorMessage(t('socialForm.error.connection'));
|
|
return;
|
|
}
|
|
await handleLoginSuccess(response);
|
|
}
|
|
}
|
|
|
|
async function handleAppleLogin(code: string, state: string): Promise<void> {
|
|
if (code && state) {
|
|
const response: string = await apiPostPublic<string>(`auth/apple`, {
|
|
code: code,
|
|
state: state,
|
|
}, lang);
|
|
if (!response) {
|
|
errorMessage(t('socialForm.error.connection'));
|
|
return;
|
|
}
|
|
await handleLoginSuccess(response);
|
|
}
|
|
}
|
|
|
|
async function handleOAuthClick(provider: 'google' | 'facebook' | 'apple'): Promise<void> {
|
|
try {
|
|
const oauthUrl = `${configs.baseUrl}auth/${provider}/desktop`;
|
|
await tauri.openExternal(oauthUrl);
|
|
} catch {
|
|
errorMessage(t('socialForm.error.connection'));
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="flex justify-center gap-3">
|
|
<button
|
|
onClick={() => handleOAuthClick('facebook')}
|
|
className="flex items-center justify-center w-14 h-14 bg-[#1877F2] hover:bg-opacity-90 text-text-primary rounded-xl transition-colors cursor-pointer"
|
|
aria-label="Login with Facebook"
|
|
>
|
|
<FacebookIcon/>
|
|
</button>
|
|
|
|
<button
|
|
onClick={() => handleOAuthClick('google')}
|
|
className="flex items-center justify-center w-14 h-14 bg-white hover:bg-opacity-90 text-[#4285F4] rounded-xl transition-colors cursor-pointer"
|
|
aria-label="Login with Google"
|
|
>
|
|
<GoogleIcon/>
|
|
</button>
|
|
|
|
<button
|
|
onClick={() => handleOAuthClick('apple')}
|
|
className="flex items-center justify-center w-14 h-14 bg-black hover:bg-opacity-90 text-white rounded-xl transition-colors cursor-pointer"
|
|
aria-label="Login with Apple"
|
|
>
|
|
<AppleIcon/>
|
|
</button>
|
|
</div>
|
|
)
|
|
}
|