external interface RestContainerChildProps<E> : Props {
var items: Array<Item<E>>
var addElement: (E) -> Unit
var updateItem: (Item<E>) -> Unit
var deleteItem: (ItemId) -> Unit
}
inline fun <reified E : Any> restContainer(
url: String,
child: FC<RestContainerChildProps<E>>,
queryId: String,
displayName: String = "RestContainer"
) = FC(displayName) { _: Props ->
val queryClient = useQueryClient()
val myQueryKey = arrayOf(queryId).unsafeCast<QueryKey>()
val query = useQuery<String, QueryError, String, QueryKey>(
queryKey = myQueryKey,
queryFn = {
fetchText(url)
}
)
invalidateRepoKey.Provider(myQueryKey) {
child {
items = Json.decodeFromString(query.data ?: "")
addElement = {
addMutation.mutateAsync(it, null)
}
updateItem = {
updateMutation.mutateAsync(it, null)
}
deleteItem = {
deleteMutation.mutateAsync(it, null)
}
}
}
inline fun <reified E : Any> restList(
cElementInList: FC<ElementInListProps<E>>,
cAddItem: FC<EditAddProps<E>>,
cEditItem: FC<EditItemProps<E>>,
displayName: String = "ListContainer"
) = FC(displayName) { props: RestContainerChildProps<E> ->
external interface ElementInListProps<E> : Props {
var element: E
}
external interface EditAddProps<E> : Props {
var saveElement: (E) -> Unit
}
external interface EditItemProps<E> : Props {
var item: Item<E>
var saveElement: (E) -> Unit
}
var editedIndex by useState(-1)
cAddItem {
saveElement = { props.addElement(it) }
}
val editedItem = props.items.getOrNull(editedIndex)
if (editedItem != null)
cEditItem {
item = editedItem
saveElement = {
props.updateItem(Item(it, editedItem.id))
}
key = editedItem.id
}
val CLessonAdd = FC<EditAddProps<Lesson>>("LessonNew") { props ->
var name by useState("")
div {
input {
type = InputType.text
value = name
onChange = { name = it.target.value }
}
button {
+"✔"
onClick = {
props.saveElement(Lesson(name))
} } } }
Route {
path = "lessons"
val list: FC<RestContainerChildProps<Lesson>> =
restList(
CLessonInList,
CLessonAdd,
CLessonEditContainer
)
element = restContainer(
Config.lessonsPath,
list,
"lessons"
).create()
}
val CAddStudentToLesson = FC<AddStudentProps>("AddStudent")
{ props ->
val queryClient = useQueryClient()
val invalidateRepoKey = useContext(invalidateRepoKey)
val addStudentMutation =
useMutation<HTTPResult, Any, StudentId, Any>(
mutationFn = { studentId ->
fetch(
"${Config.lessonsPath}/${props.lesson.id}/students/$studentId",
)},
options = jso {
onSuccess = { _: Any, _: Any, _: Any? ->
queryClient.invalidateQueries<Any>(invalidateRepoKey)
}})