2024-01-25 09:57:57 +00:00
import { createInfiniteScroll } from '@solid-primitives/pagination'
import { clsx } from 'clsx'
import { createEffect , createSignal , For , on , Show } from 'solid-js'
import { useInbox } from '../../../context/inbox'
import { useLocalize } from '../../../context/localize'
import { Author } from '../../../graphql/schema/core.gen'
import { hideModal } from '../../../stores/ui'
import { useAuthorsStore } from '../../../stores/zine/authors'
import { AuthorBadge } from '../../Author/AuthorBadge'
import { Button } from '../Button'
import { DropdownSelect } from '../DropdownSelect'
import { Loading } from '../Loading'
import styles from './InviteMembers.module.scss'
type InviteAuthor = Author & { selected : boolean }
type Props = {
title? : string
variant ? : 'coauthors' | 'recipients'
}
const PAGE_SIZE = 50
export const InviteMembers = ( props : Props ) = > {
const { t } = useLocalize ( )
const roles = [
{
title : t ( 'Editor' ) ,
description : t ( 'Can write and edit text directly, and accept or reject suggestions from others' ) ,
} ,
{
title : t ( 'Co-author' ) ,
description : t ( 'Can make any changes, accept or reject suggestions, and share access with others' ) ,
} ,
{
title : t ( 'Commentator' ) ,
description : t ( 'Can offer edits and comments, but cannot edit the post or share access with others' ) ,
} ,
]
const { sortedAuthors } = useAuthorsStore ( { sortBy : 'name' } )
2024-01-27 06:21:48 +00:00
const {
actions : { loadChats , createChat } ,
} = useInbox ( )
2024-01-25 09:57:57 +00:00
const [ authorsToInvite , setAuthorsToInvite ] = createSignal < InviteAuthor [ ] > ( )
const [ searchResultAuthors , setSearchResultAuthors ] = createSignal < Author [ ] > ( )
const [ collectionToInvite , setCollectionToInvite ] = createSignal < number [ ] > ( [ ] )
const fetcher = async ( page : number ) = > {
await new Promise ( ( resolve , reject ) = > {
const checkDataLoaded = ( ) = > {
if ( sortedAuthors ( ) . length > 0 ) {
resolve ( true )
} else {
setTimeout ( checkDataLoaded , 100 )
}
}
setTimeout ( ( ) = > reject ( new Error ( 'Timeout waiting for sortedAuthors' ) ) , 10000 )
checkDataLoaded ( )
} )
const start = page * PAGE_SIZE
const end = start + PAGE_SIZE
2024-01-25 19:16:38 +00:00
const authors = authorsToInvite ( ) ? . map ( ( author ) = > ( { . . . author , selected : false } ) )
return authors ? . slice ( start , end )
2024-01-25 09:57:57 +00:00
}
const [ pages , infiniteScrollLoader , { end } ] = createInfiniteScroll ( fetcher )
createEffect (
on (
( ) = > sortedAuthors ( ) ,
( currentAuthors ) = > {
setAuthorsToInvite ( currentAuthors . map ( ( author ) = > ( { . . . author , selected : false } ) ) )
} ,
{ defer : true } ,
) ,
)
const handleInputChange = async ( value : string ) = > {
if ( value . length > 1 ) {
const match = authorsToInvite ( ) . filter ( ( author ) = >
author . name . toLowerCase ( ) . includes ( value . toLowerCase ( ) ) ,
)
setSearchResultAuthors ( match )
} else {
setSearchResultAuthors ( )
}
}
const handleInvite = ( id ) = > {
setCollectionToInvite ( ( prev ) = > [ . . . prev , id ] )
}
const handleCloseModal = ( ) = > {
setSearchResultAuthors ( )
setCollectionToInvite ( )
hideModal ( )
}
const handleCreate = async ( ) = > {
try {
2024-01-27 06:21:48 +00:00
const initChat = await createChat ( collectionToInvite ( ) , 'chat Title' )
2024-01-25 09:57:57 +00:00
console . debug ( '[components.Inbox] create chat result:' , initChat )
hideModal ( )
2024-01-27 06:21:48 +00:00
await loadChats ( )
2024-01-25 09:57:57 +00:00
} catch ( error ) {
console . error ( 'handleCreate chat' , error )
}
}
return (
2024-02-02 04:31:25 +00:00
< >
2024-01-25 09:57:57 +00:00
< h2 > { props . title || t ( 'Invite collaborators' ) } < / h2 >
< div class = { clsx ( styles . InviteMembers ) } >
< div class = { styles . searchHeader } >
< div class = { styles . field } >
< input
class = { styles . input }
type = "text"
placeholder = { t ( 'Write your colleagues name or email' ) }
onChange = { ( e ) = > {
if ( props . variant === 'recipients' ) return
handleInputChange ( e . target . value )
} }
onInput = { ( e ) = > {
if ( props . variant === 'coauthors' ) return
handleInputChange ( e . target . value )
} }
/ >
< Show when = { props . variant === 'coauthors' } >
< DropdownSelect selectItems = { roles } / >
< / Show >
< / div >
< Show when = { props . variant === 'coauthors' } >
< Button class = { styles . searchButton } variant = { 'bordered' } size = { 'M' } value = { t ( 'Search' ) } / >
< / Show >
< / div >
< Show when = { props . variant === 'coauthors' } >
< div class = { styles . teaser } >
< h3 > { t ( 'Coming soon' ) } < / h3 >
< p >
{ t (
'We are working on collaborative editing of articles and in the near future you will have an amazing opportunity - to create together with your colleagues' ,
) }
< / p >
< / div >
< / Show >
< Show when = { props . variant === 'recipients' } >
< div class = { styles . authors } >
< For each = { searchResultAuthors ( ) ? ? pages ( ) } >
{ ( author ) = > (
< div class = { styles . author } >
< AuthorBadge
author = { author }
nameOnly = { true }
inviteView = { true }
onInvite = { ( id ) = > handleInvite ( id ) }
/ >
< / div >
) }
< / For >
< Show when = { ! end ( ) } >
< div use : infiniteScrollLoader class = { styles . loading } >
< div class = { styles . icon } >
< Loading size = "tiny" / >
< / div >
< div > { t ( 'Loading' ) } < / div >
< / div >
< / Show >
< / div >
< / Show >
< div class = { styles . actions } >
< Button variant = { 'bordered' } size = { 'M' } value = { t ( 'Cancel' ) } onClick = { handleCloseModal } / >
< Button
variant = { 'primary' }
size = { 'M' }
disabled = { collectionToInvite ( ) . length === 0 }
value = { t ( 'Start dialog' ) }
onClick = { handleCreate }
/ >
< / div >
< / div >
2024-02-02 04:31:25 +00:00
< / >
2024-01-25 09:57:57 +00:00
)
}