2023-03-06 10:53:35 +00:00
import { useCallback , useState } from "react" ;
2022-08-26 00:11:41 +00:00
2023-02-16 22:39:57 +00:00
import type { EventLocationType } from "@calcom/app-store/locations" ;
import { getEventLocationTypeFromApp } from "@calcom/app-store/locations" ;
2023-03-06 13:46:21 +00:00
import { AppSetDefaultLinkDialog } from "@calcom/features/apps/components/AppSetDefaultLinkDialog" ;
2023-03-06 10:53:35 +00:00
import { BulkEditDefaultConferencingModal } from "@calcom/features/eventtypes/components/BulkEditDefaultConferencingModal" ;
2023-01-05 17:00:16 +00:00
import { getLayout } from "@calcom/features/settings/layouts/SettingsLayout" ;
2022-08-26 00:11:41 +00:00
import { useLocale } from "@calcom/lib/hooks/useLocale" ;
2022-09-15 09:05:26 +00:00
import { trpc } from "@calcom/trpc/react" ;
2022-11-23 02:55:25 +00:00
import {
Button ,
Dialog ,
2022-11-28 19:14:38 +00:00
DialogClose ,
2022-11-23 02:55:25 +00:00
DialogContent ,
2022-11-28 19:14:38 +00:00
DialogFooter ,
2022-11-23 02:55:25 +00:00
Dropdown ,
DropdownMenuContent ,
DropdownMenuItem ,
2023-01-15 11:40:40 +00:00
DropdownItem ,
2022-11-23 02:55:25 +00:00
DropdownMenuTrigger ,
List ,
Meta ,
showToast ,
SkeletonContainer ,
SkeletonText ,
} from "@calcom/ui" ;
2023-05-09 16:45:53 +00:00
import { AlertCircle , MoreHorizontal , Trash , Video , Plus } from "@calcom/ui/components/icon" ;
2022-08-26 00:11:41 +00:00
2023-01-19 15:02:01 +00:00
import AppListCard from "@components/AppListCard" ;
2023-04-18 18:45:32 +00:00
import PageWrapper from "@components/PageWrapper" ;
2023-01-19 15:02:01 +00:00
2022-12-07 20:53:44 +00:00
const SkeletonLoader = ( { title , description } : { title : string ; description : string } ) = > {
2022-09-15 09:05:26 +00:00
return (
< SkeletonContainer >
2022-12-07 20:53:44 +00:00
< Meta title = { title } description = { description } / >
2023-06-22 22:25:37 +00:00
< div className = "divide-subtle mb-8 mt-6 space-y-6" >
2022-09-15 09:05:26 +00:00
< SkeletonText className = "h-8 w-full" / >
< SkeletonText className = "h-8 w-full" / >
< / div >
< / SkeletonContainer >
) ;
} ;
2022-08-26 00:11:41 +00:00
2023-05-09 16:45:53 +00:00
const AddConferencingButton = ( ) = > {
const { t } = useLocale ( ) ;
return (
< >
< Button color = "secondary" StartIcon = { Plus } href = "/apps/categories/video" >
{ t ( "add_conferencing_app" ) }
< / Button >
< / >
) ;
} ;
2022-09-15 09:05:26 +00:00
const ConferencingLayout = ( ) = > {
2022-08-26 00:11:41 +00:00
const { t } = useLocale ( ) ;
2022-09-15 09:05:26 +00:00
const utils = trpc . useContext ( ) ;
2023-02-13 22:55:32 +00:00
const { data : defaultConferencingApp , isLoading : defaultConferencingAppLoading } =
trpc . viewer . getUsersDefaultConferencingApp . useQuery ( ) ;
const { data : apps , isLoading } = trpc . viewer . integrations . useQuery ( {
variant : "conferencing" ,
onlyInstalled : true ,
} ) ;
2022-11-10 23:40:01 +00:00
const deleteAppMutation = trpc . viewer . deleteCredential . useMutation ( {
2022-09-15 09:05:26 +00:00
onSuccess : ( ) = > {
showToast ( "Integration deleted successfully" , "success" ) ;
2022-11-10 23:40:01 +00:00
utils . viewer . integrations . invalidate ( { variant : "conferencing" , onlyInstalled : true } ) ;
2022-09-15 09:05:26 +00:00
setDeleteAppModal ( false ) ;
} ,
onError : ( ) = > {
showToast ( "Error deleting app" , "error" ) ;
setDeleteAppModal ( false ) ;
} ,
} ) ;
2022-08-26 00:11:41 +00:00
2023-03-06 10:53:35 +00:00
const onSuccessCallback = useCallback ( ( ) = > {
setBulkUpdateModal ( true ) ;
showToast ( "Default app updated successfully" , "success" ) ;
} , [ ] ) ;
2023-02-13 22:55:32 +00:00
const updateDefaultAppMutation = trpc . viewer . updateUserDefaultConferencingApp . useMutation ( {
2023-03-08 16:17:08 +00:00
onSuccess : async ( ) = > {
await utils . viewer . getUsersDefaultConferencingApp . invalidate ( ) ;
onSuccessCallback ( ) ;
} ,
2023-02-14 13:19:45 +00:00
onError : ( error ) = > {
showToast ( ` Error: ${ error . message } ` , "error" ) ;
} ,
2023-02-13 22:55:32 +00:00
} ) ;
2022-09-15 09:05:26 +00:00
const [ deleteAppModal , setDeleteAppModal ] = useState ( false ) ;
2023-03-06 10:53:35 +00:00
const [ bulkUpdateModal , setBulkUpdateModal ] = useState ( false ) ;
2023-02-13 22:55:32 +00:00
const [ locationType , setLocationType ] = useState < ( EventLocationType & { slug : string } ) | undefined > (
undefined
) ;
2022-09-15 09:05:26 +00:00
const [ deleteCredentialId , setDeleteCredentialId ] = useState < number > ( 0 ) ;
2022-08-26 00:11:41 +00:00
2023-02-13 22:55:32 +00:00
if ( isLoading || defaultConferencingAppLoading )
2022-12-07 20:53:44 +00:00
return < SkeletonLoader title = { t ( "conferencing" ) } description = { t ( "conferencing_description" ) } / > ;
2022-08-26 00:11:41 +00:00
return (
2023-04-05 18:14:46 +00:00
< div className = "bg-default w-full sm:mx-0 xl:mt-0" >
2023-05-09 16:45:53 +00:00
< Meta
title = { t ( "conferencing" ) }
description = { t ( "conferencing_description" ) }
CTA = { < AddConferencingButton / > }
/ >
2022-11-23 02:55:25 +00:00
< List >
2022-09-15 09:05:26 +00:00
{ apps ? . items &&
apps . items
. map ( ( app ) = > ( { . . . app , title : app.title || app . name } ) )
2023-02-13 22:55:32 +00:00
. map ( ( app ) = > {
const appSlug = app ? . slug ;
const appIsDefault =
appSlug === defaultConferencingApp ? . appSlug ||
( appSlug === "daily-video" && ! defaultConferencingApp ? . appSlug ) ; // Default to cal video if the user doesnt have it set (we do this on new account creation but not old)
return (
< AppListCard
description = { app . description }
title = { app . title }
logo = { app . logo }
key = { app . title }
isDefault = { appIsDefault } // @TODO: Handle when a user doesnt have this value set
actions = {
< div >
< Dropdown >
< DropdownMenuTrigger asChild >
2023-04-12 15:26:31 +00:00
< Button StartIcon = { MoreHorizontal } variant = "icon" color = "secondary" / >
2023-02-13 22:55:32 +00:00
< / DropdownMenuTrigger >
< DropdownMenuContent >
{ ! appIsDefault && (
< DropdownMenuItem >
< DropdownItem
type = "button"
color = "secondary"
2023-04-12 15:26:31 +00:00
StartIcon = { Video }
2023-02-13 22:55:32 +00:00
onClick = { ( ) = > {
const locationType = getEventLocationTypeFromApp (
app ? . locationOption ? . value ? ? ""
) ;
if ( locationType ? . linkType === "static" ) {
setLocationType ( { . . . locationType , slug : appSlug } ) ;
} else {
updateDefaultAppMutation . mutate ( {
appSlug ,
} ) ;
}
} } >
2023-06-08 13:37:54 +00:00
{ t ( "set_as_default" ) }
2023-02-13 22:55:32 +00:00
< / DropdownItem >
< / DropdownMenuItem >
) }
< DropdownMenuItem >
< DropdownItem
type = "button"
color = "destructive"
disabled = { app . isGlobal }
2023-04-12 15:26:31 +00:00
StartIcon = { Trash }
2023-02-13 22:55:32 +00:00
onClick = { ( ) = > {
setDeleteCredentialId ( app . credentialIds [ 0 ] ) ;
setDeleteAppModal ( true ) ;
} } >
{ t ( "remove_app" ) }
< / DropdownItem >
< / DropdownMenuItem >
< / DropdownMenuContent >
< / Dropdown >
< / div >
}
/ >
) ;
} ) }
2022-09-09 12:57:31 +00:00
< / List >
2022-09-15 09:05:26 +00:00
< Dialog open = { deleteAppModal } onOpenChange = { setDeleteAppModal } >
< DialogContent
title = { t ( "Remove app" ) }
description = { t ( "are_you_sure_you_want_to_remove_this_app" ) }
type = "confirmation"
2023-04-12 15:26:31 +00:00
Icon = { AlertCircle } >
2022-11-28 19:14:38 +00:00
< DialogFooter >
< Button color = "primary" onClick = { ( ) = > deleteAppMutation . mutate ( { id : deleteCredentialId } ) } >
{ t ( "yes_remove_app" ) }
< / Button >
< DialogClose / >
< / DialogFooter >
< / DialogContent >
2022-09-15 09:05:26 +00:00
< / Dialog >
2023-02-13 22:55:32 +00:00
{ locationType && (
2023-03-06 13:46:21 +00:00
< AppSetDefaultLinkDialog
2023-03-06 10:53:35 +00:00
locationType = { locationType }
setLocationType = { setLocationType }
onSuccess = { onSuccessCallback }
/ >
) }
{ bulkUpdateModal && (
< BulkEditDefaultConferencingModal open = { bulkUpdateModal } setOpen = { setBulkUpdateModal } / >
2023-02-13 22:55:32 +00:00
) }
2022-08-26 00:11:41 +00:00
< / div >
) ;
} ;
ConferencingLayout . getLayout = getLayout ;
2023-04-18 18:45:32 +00:00
ConferencingLayout . PageWrapper = PageWrapper ;
2022-08-26 00:11:41 +00:00
export default ConferencingLayout ;