'use client';
import { useModals } from '@mantine/modals';
import React, { FC, useCallback, useEffect, useMemo } from 'react';
import { useFetch } from '@gitroom/helpers/utils/custom.fetch';
import { Input } from '@gitroom/react/form/input';
import { FieldValues, FormProvider, useForm } from 'react-hook-form';
import { Button } from '@gitroom/react/form/button';
import { classValidatorResolver } from '@hookform/resolvers/class-validator';
import { ApiKeyDto } from '@gitroom/nestjs-libraries/dtos/integrations/api.key.dto';
import { useRouter, useSearchParams } from 'next/navigation';
import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component';
import { useVariables } from '@gitroom/react/helpers/variable.context';
import { useToaster } from '@gitroom/react/toaster/toaster';
import { object, string } from 'yup';
import { yupResolver } from '@hookform/resolvers/yup';
import { web3List } from '@gitroom/frontend/components/launches/web3/web3.list';
import { useT } from '@gitroom/react/translation/get.transation.service.client';
import { ModalWrapperComponent } from '@gitroom/frontend/components/new-launch/modal.wrapper.component';
const resolver = classValidatorResolver(ApiKeyDto);
export const useAddProvider = (update?: () => void) => {
const modal = useModals();
const fetch = useFetch();
return useCallback(async () => {
const data = await (await fetch('/integrations')).json();
modal.openModal({
title: '',
withCloseButton: false,
classNames: {
modal: 'text-textColor',
},
size: 'auto',
children: (
),
});
}, []);
};
export const AddProviderButton: FC<{
update?: () => void;
}> = (props) => {
const { update } = props;
const query = useSearchParams();
const add = useAddProvider(update);
const t = useT();
useEffect(() => {
if (query.get('onboarding')) {
add();
}
}, []);
return (
);
};
export const ApiModal: FC<{
identifier: string;
name: string;
update?: () => void;
close?: () => void;
}> = (props) => {
const { update, name, close: closePopup } = props;
const fetch = useFetch();
const router = useRouter();
const modal = useModals();
const methods = useForm({
mode: 'onChange',
resolver,
});
const close = useCallback(() => {
if (closePopup) {
return closePopup();
}
modal.closeAll();
}, []);
const submit = useCallback(async (data: FieldValues) => {
const add = await fetch(
`/integrations/article/${props.identifier}/connect`,
{
method: 'POST',
body: JSON.stringify({
api: data.api,
}),
}
);
if (add.ok) {
if (closePopup) {
closePopup();
} else {
modal.closeAll();
}
router.refresh();
if (update) update();
return;
}
methods.setError('api', {
message: 'Invalid API key',
});
}, []);
const t = useT();
return (
);
};
export const UrlModal: FC<{
gotoUrl(url: string): void;
}> = (props) => {
const { gotoUrl } = props;
const methods = useForm({
mode: 'onChange',
});
const t = useT();
const submit = useCallback(async (data: FieldValues) => {
gotoUrl(data.url);
}, []);
return (
);
};
export const CustomVariables: FC<{
variables: Array<{
key: string;
label: string;
defaultValue?: string;
validation: string;
type: 'text' | 'password';
}>;
close?: () => void;
identifier: string;
gotoUrl(url: string): void;
}> = (props) => {
const { close, gotoUrl, identifier, variables } = props;
const modals = useModals();
const schema = useMemo(() => {
return object({
...variables.reduce((aIcc, item) => {
const splitter = item.validation.split('/');
const regex = new RegExp(
splitter.slice(1, -1).join('/'),
splitter.pop()
);
return {
...aIcc,
[item.key]: string()
.matches(regex, `${item.label} is invalid`)
.required(),
};
}, {}),
});
}, [variables]);
const methods = useForm({
mode: 'onChange',
resolver: yupResolver(schema),
values: variables.reduce(
(acc, item) => ({
...acc,
...(item.defaultValue
? {
[item.key]: item.defaultValue,
}
: {}),
}),
{}
),
});
const submit = useCallback(
async (data: FieldValues) => {
gotoUrl(
`/integrations/social/${identifier}?state=nostate&code=${Buffer.from(
JSON.stringify(data)
).toString('base64')}`
);
},
[variables]
);
const t = useT();
return (
);
};
export const AddProviderComponent: FC<{
social: Array<{
identifier: string;
name: string;
toolTip?: string;
isExternal: boolean;
isWeb3: boolean;
customFields?: Array<{
key: string;
label: string;
validation: string;
type: 'text' | 'password';
}>;
}>;
article: Array<{
identifier: string;
name: string;
}>;
update?: () => void;
}> = (props) => {
const { update, social, article } = props;
const { isGeneral } = useVariables();
const toaster = useToaster();
const router = useRouter();
const fetch = useFetch();
const modal = useModals();
const getSocialLink = useCallback(
(
identifier: string,
isExternal: boolean,
isWeb3: boolean,
customFields?: Array<{
key: string;
label: string;
validation: string;
defaultValue?: string;
type: 'text' | 'password';
}>
) =>
async () => {
const openWeb3 = async () => {
const { component: Web3Providers } = web3List.find(
(item) => item.identifier === identifier
)!;
const { url } = await (
await fetch(`/integrations/social/${identifier}`)
).json();
modal.openModal({
title: '',
withCloseButton: false,
classNames: {
modal: 'bg-transparent text-textColor',
},
children: (
{
window.location.href = `/integrations/social/${identifier}?code=${code}&state=${newState}`;
}}
nonce={url}
/>
),
});
return;
};
const gotoIntegration = async (externalUrl?: string) => {
const { url, err } = await (
await fetch(
`/integrations/social/${identifier}${
externalUrl ? `?externalUrl=${externalUrl}` : ``
}`
)
).json();
if (err) {
toaster.show('Could not connect to the platform', 'warning');
return;
}
window.location.href = url;
};
if (isWeb3) {
openWeb3();
return;
}
if (isExternal) {
modal.closeAll();
modal.openModal({
title: '',
withCloseButton: false,
classNames: {
modal: 'bg-transparent text-textColor',
},
children: (
),
});
return;
}
if (customFields) {
modal.closeAll();
modal.openModal({
title: '',
withCloseButton: false,
classNames: {
modal: 'bg-transparent text-textColor',
},
children: (
router.push(url)}
variables={customFields}
/>
),
});
return;
}
await gotoIntegration();
},
[]
);
const close = useCallback(() => {
modal.closeAll();
}, []);
const showApiButton = useCallback(
(identifier: string, name: string) => async () => {
modal.openModal({
title: '',
withCloseButton: false,
classNames: {
modal: 'bg-transparent text-textColor',
},
children: (
),
});
},
[]
);
const t = useT();
return (
{t('social', 'Social')}
{social.map((item) => (
{item.identifier === 'youtube' ? (

) : (

)}
{item.name}
{!!item.toolTip && (
)}
))}
{!isGeneral && (
{t('articles', 'Articles')}
{article.map((item) => (
))}
)}
);
};