'use client';
import { AddProviderButton } from '@gitroom/frontend/components/launches/add.provider.component';
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
import Image from 'next/image';
import { groupBy, orderBy } from 'lodash';
import { CalendarWeekProvider } from '@gitroom/frontend/components/launches/calendar.context';
import { Filters } from '@gitroom/frontend/components/launches/filters';
import { useFetch } from '@gitroom/helpers/utils/custom.fetch';
import useSWR from 'swr';
import { LoadingComponent } from '@gitroom/frontend/components/layout/loading';
import clsx from 'clsx';
import { useUser } from '../layout/user.context';
import { Menu } from '@gitroom/frontend/components/launches/menu/menu';
import { useRouter, useSearchParams } from 'next/navigation';
import { Integration } from '@prisma/client';
import ImageWithFallback from '@gitroom/react/helpers/image.with.fallback';
import { useToaster } from '@gitroom/react/toaster/toaster';
import { useFireEvents } from '@gitroom/helpers/utils/use.fire.events';
import { Calendar } from './calendar';
import { useDrag, useDrop } from 'react-dnd';
import { DNDProvider } from '@gitroom/frontend/components/launches/helpers/dnd.provider';
interface MenuComponentInterface {
refreshChannel: (
integration: Integration & { identifier: string }
) => () => void;
continueIntegration: (integration: Integration) => () => void;
totalNonDisabledChannels: number;
mutate: (shouldReload?: boolean) => void;
update: (shouldReload: boolean) => void;
}
export const MenuGroupComponent: FC<
MenuComponentInterface & {
changeItemGroup: (id: string, group: string) => void;
group: {
id: string;
name: string;
values: Array<
Integration & {
identifier: string;
changeProfilePicture: boolean;
changeNickName: boolean;
}
>;
};
}
> = (props) => {
const {
group,
mutate,
update,
continueIntegration,
totalNonDisabledChannels,
refreshChannel,
changeItemGroup,
} = props;
const [collectedProps, drop] = useDrop(() => ({
accept: 'menu',
drop: (item: { id: string }, monitor) => {
changeItemGroup(item.id, group.id);
},
collect: (monitor) => ({
isOver: !!monitor.isOver(),
}),
}));
return (
{collectedProps.isOver && (
)}
{!!group.name &&
{group.name}
}
{group.values.map((integration) => (
))}
);
};
export const MenuComponent: FC<
MenuComponentInterface & {
integration: Integration & {
identifier: string;
changeProfilePicture: boolean;
changeNickName: boolean;
};
}
> = (props) => {
const {
totalNonDisabledChannels,
continueIntegration,
refreshChannel,
mutate,
update,
integration,
} = props;
const user = useUser();
const [collected, drag, dragPreview] = useDrag(() => ({
type: 'menu',
item: { id: integration.id },
}));
return (
{(integration.inBetweenSteps || integration.refreshNeeded) && (
)}
{integration.identifier === 'youtube' ? (

) : (
)}
{integration.name}
);
};
export const LaunchesComponent = () => {
const fetch = useFetch();
const router = useRouter();
const search = useSearchParams();
const toast = useToaster();
const fireEvents = useFireEvents();
const [reload, setReload] = useState(false);
const load = useCallback(async (path: string) => {
return (await (await fetch(path)).json()).integrations;
}, []);
const {
isLoading,
data: integrations,
mutate,
} = useSWR('/integrations/list', load, {
fallbackData: [],
});
const totalNonDisabledChannels = useMemo(() => {
return (
integrations?.filter((integration: any) => !integration.disabled)
?.length || 0
);
}, [integrations]);
const changeItemGroup = useCallback(
async (id: string, group: string) => {
mutate(
integrations.map((integration: any) => {
if (integration.id === id) {
return { ...integration, customer: { id: group } };
}
return integration;
}),
false
);
await fetch(`/integrations/${id}/group`, {
method: 'PUT',
body: JSON.stringify({ group }),
});
mutate();
},
[integrations]
);
const sortedIntegrations = useMemo(() => {
return orderBy(
integrations,
['type', 'disabled', 'identifier'],
['desc', 'asc', 'asc']
);
}, [integrations]);
const menuIntegrations = useMemo(() => {
return orderBy(
Object.values(
groupBy(sortedIntegrations, (o) => o?.customer?.id || '')
).map((p) => ({
name: (p[0].customer?.name || '') as string,
id: (p[0].customer?.id || '') as string,
isEmpty: p.length === 0,
values: orderBy(
p,
['type', 'disabled', 'identifier'],
['desc', 'asc', 'asc']
),
})),
['isEmpty', 'name'],
['desc', 'asc']
);
}, [sortedIntegrations]);
const update = useCallback(async (shouldReload: boolean) => {
if (shouldReload) {
setReload(true);
}
await mutate();
if (shouldReload) {
setReload(false);
}
}, []);
const continueIntegration = useCallback(
(integration: any) => async () => {
router.push(
`/launches?added=${integration.identifier}&continue=${integration.id}`
);
},
[]
);
const refreshChannel = useCallback(
(integration: Integration & { identifier: string }) => async () => {
const { url } = await (
await fetch(
`/integrations/social/${integration.identifier}?refresh=${integration.internalId}`,
{
method: 'GET',
}
)
).json();
window.location.href = url;
},
[]
);
useEffect(() => {
if (typeof window === 'undefined') {
return;
}
if (search.get('msg')) {
toast.show(search.get('msg')!, 'warning');
}
if (search.get('added')) {
fireEvents('channel_added');
}
if (window.opener) {
window.close();
}
}, []);
if (isLoading || reload) {
return ;
}
// @ts-ignore
return (
Channels
{sortedIntegrations.length === 0 && (
No channels
)}
{menuIntegrations.map((menu) => (
))}
update(true)} />
{/*{sortedIntegrations?.length > 0 && user?.tier?.ai && }*/}
);
};