mirror of
https://github.com/Steffo99/sophon.git
synced 2024-12-22 14:54:22 +00:00
✨ Create GroupListBox
This commit is contained in:
parent
a765681c3f
commit
a7eb7a78b4
4 changed files with 141 additions and 2 deletions
|
@ -6,6 +6,7 @@ import {AuthorizationRouter} from "./components/authorization/AuthorizationRoute
|
|||
import {AuthorizationStepPage} from "./components/authorization/AuthorizationStepPage"
|
||||
import {SophonFooter} from "./components/elements/SophonFooter"
|
||||
import {ErrorCatcherBox} from "./components/errors/ErrorCatcherBox"
|
||||
import {GroupListBox} from "./components/group/GroupListBox"
|
||||
import {GroupRouter} from "./components/group/GroupRouter"
|
||||
import {InstanceRouter} from "./components/instance/InstanceRouter"
|
||||
import {InstanceStepPage} from "./components/instance/InstanceStepPage"
|
||||
|
@ -17,7 +18,7 @@ import {InstanceProvider} from "./contexts/instance"
|
|||
import {ThemeProvider} from "./contexts/theme"
|
||||
|
||||
|
||||
function App({...props}: RouteComponentProps) {
|
||||
function App({}: RouteComponentProps) {
|
||||
return (
|
||||
<InstanceProvider>
|
||||
<InstanceRouter
|
||||
|
@ -32,7 +33,7 @@ function App({...props}: RouteComponentProps) {
|
|||
</>}
|
||||
selectedRoute={() => <>
|
||||
<GroupRouter
|
||||
unselectedRoute={DebugBox}
|
||||
unselectedRoute={(props) => <GroupListBox {...props}/>}
|
||||
selectedRoute={DebugBox}
|
||||
/>
|
||||
</>}
|
||||
|
|
22
frontend/src/components/group/GroupListBox.tsx
Normal file
22
frontend/src/components/group/GroupListBox.tsx
Normal file
|
@ -0,0 +1,22 @@
|
|||
import {Box, Heading} from "@steffo/bluelib-react"
|
||||
import * as React from "react"
|
||||
import {SophonResearchGroup} from "../../types/SophonTypes"
|
||||
import {ListRouteProps} from "../routing/ViewSetRouter"
|
||||
import {GroupResourcePanel} from "./GroupResourcePanel"
|
||||
|
||||
|
||||
export interface GroupListBoxProps extends ListRouteProps<SophonResearchGroup> {
|
||||
|
||||
}
|
||||
|
||||
|
||||
export function GroupListBox({viewSet}: GroupListBoxProps): JSX.Element {
|
||||
return (
|
||||
<Box>
|
||||
<Heading level={3}>
|
||||
Research groups
|
||||
</Heading>
|
||||
{viewSet.resources?.map(res => <GroupResourcePanel resource={res} key={res.value.slug}/>)}
|
||||
</Box>
|
||||
)
|
||||
}
|
37
frontend/src/components/group/GroupResourcePanel.tsx
Normal file
37
frontend/src/components/group/GroupResourcePanel.tsx
Normal file
|
@ -0,0 +1,37 @@
|
|||
import {faEnvelope, faGlobe} from "@fortawesome/free-solid-svg-icons"
|
||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"
|
||||
import * as React from "react"
|
||||
import {ManagedResource} from "../../hooks/useManagedViewSet"
|
||||
import {SophonResearchGroup} from "../../types/SophonTypes"
|
||||
import {Link} from "../elements/Link"
|
||||
import {ResourcePanel} from "../elements/ResourcePanel"
|
||||
|
||||
|
||||
export interface GroupResourcePanelProps {
|
||||
resource: ManagedResource<SophonResearchGroup>,
|
||||
}
|
||||
|
||||
|
||||
export function GroupResourcePanel({resource}: GroupResourcePanelProps): JSX.Element {
|
||||
const icon = resource.value.access === "OPEN" ? faGlobe : faEnvelope
|
||||
const members = resource.value.members.length
|
||||
|
||||
return (
|
||||
<ResourcePanel>
|
||||
<ResourcePanel.Icon>
|
||||
<FontAwesomeIcon icon={icon}/>
|
||||
</ResourcePanel.Icon>
|
||||
<ResourcePanel.Name>
|
||||
<Link href={`g/${resource.value.slug}/`}>
|
||||
{resource.value.name}
|
||||
</Link>
|
||||
</ResourcePanel.Name>
|
||||
<ResourcePanel.Text>
|
||||
{members} member{members !== 1 ? "s" : ""}
|
||||
</ResourcePanel.Text>
|
||||
<ResourcePanel.Buttons>
|
||||
|
||||
</ResourcePanel.Buttons>
|
||||
</ResourcePanel>
|
||||
)
|
||||
}
|
79
frontend/src/contexts/group.tsx
Normal file
79
frontend/src/contexts/group.tsx
Normal file
|
@ -0,0 +1,79 @@
|
|||
import * as React from "react"
|
||||
import {ContextData} from "../types/ContextTypes"
|
||||
import {WithChildren} from "../types/ExtraTypes"
|
||||
|
||||
// States
|
||||
|
||||
type GroupSelected = {
|
||||
bluelib: "sophon" | "royalblue" | "hacker" | "paper",
|
||||
title: string,
|
||||
}
|
||||
|
||||
|
||||
// Actions
|
||||
|
||||
type GroupSet = {
|
||||
type: "set",
|
||||
bluelib: "sophon" | "royalblue" | "hacker" | "paper",
|
||||
title: string,
|
||||
}
|
||||
|
||||
type GroupReset = {
|
||||
type: "reset",
|
||||
}
|
||||
|
||||
|
||||
// Composition
|
||||
|
||||
export type GroupState = GroupSelected
|
||||
type GroupAction = GroupSet | GroupReset
|
||||
export type GroupContextData = ContextData<GroupState, GroupAction> | undefined
|
||||
|
||||
|
||||
// Definitions
|
||||
|
||||
const groupDefaultState: GroupState = {
|
||||
bluelib: "sophon",
|
||||
title: "Sophon",
|
||||
}
|
||||
|
||||
const groupReducer: React.Reducer<GroupState, GroupAction> = (prevState, action) => {
|
||||
switch(action.type) {
|
||||
case "set":
|
||||
// Bail out if trying to set to the same state as earlier
|
||||
if(prevState.bluelib === action.bluelib && prevState.title === action.title) {
|
||||
return prevState
|
||||
}
|
||||
|
||||
return {
|
||||
bluelib: action.bluelib,
|
||||
title: action.title,
|
||||
}
|
||||
case "reset":
|
||||
return groupDefaultState
|
||||
}
|
||||
}
|
||||
|
||||
const groupContext = React.createContext<GroupContextData>(undefined)
|
||||
const GroupContext = groupContext
|
||||
|
||||
|
||||
// Hooks
|
||||
|
||||
export function useGroupReducer(): GroupContextData {
|
||||
const [state, dispatch] = React.useReducer(groupReducer, groupDefaultState)
|
||||
return {state, dispatch}
|
||||
}
|
||||
|
||||
export function useGroupContext(): GroupContextData {
|
||||
return React.useContext(groupContext)
|
||||
}
|
||||
|
||||
|
||||
// Components
|
||||
|
||||
export function GroupProvider({children}: WithChildren): JSX.Element {
|
||||
const reducer = useGroupReducer()
|
||||
|
||||
return <GroupContext.Provider value={reducer} children={children}/>
|
||||
}
|
Loading…
Reference in a new issue