import React, {useState, useRef, useLayoutEffect, useReducer} from 'react'; import './CreateLeague.css'; import twemoji from 'twemoji'; import $, {getJSON} from 'jquery'; interface LeagueStructureState { subleagues: SubleagueState[] } interface SubleagueState { name: string id: string|number divisions: DivisionState[] } interface DivisionState { name: string id: string|number teams: TeamState[] } interface TeamState { name: string id: string|number } type LeagueReducerActions = {type: 'remove_subleague', subleague_index: number} | {type: 'add_subleague'} | {type: 'rename_subleague', subleague_index: number, name: string} | {type: 'remove_divisions', division_index: number} | {type: 'add_divisions'} | {type: 'rename_division', subleague_index: number, division_index: number, name: string} | {type: 'remove_team', subleague_index: number, division_index: number, name:string} | {type: 'add_team', subleague_index:number, division_index:number, name:string} type DistributiveOmit = T extends any ? Omit : never; let getUID = function() { // does NOT generate UUIDs. Meant to create list keys ONLY let id = 0; return function() { return id++} }() function leagueStructureReducer(state: LeagueStructureState, action: LeagueReducerActions): LeagueStructureState { switch (action.type) { case 'remove_subleague': return {subleagues: removeIndex(state.subleagues, action.subleague_index)}; case 'add_subleague': return {subleagues: state.subleagues.concat([{ name: "", id: getUID(), divisions: arrayOf(state.subleagues[0].divisions.length, i => ({ name: "", id: getUID(), teams: [] })) }])}; case 'rename_subleague': return replaceSubleague(state, action.subleague_index, subleague => ({ name: action.name, id: subleague.id, divisions: subleague.divisions })); case 'remove_divisions': return {subleagues: state.subleagues.map(subleague => ({ name: subleague.name, id: subleague.id, divisions: removeIndex(subleague.divisions, action.division_index) }))}; case 'add_divisions': return {subleagues: state.subleagues.map(subleague => ({ name: subleague.name, id: subleague.id, divisions: subleague.divisions.concat([{ name: "", id: getUID(), teams: [] }]) }))}; case 'rename_division': return replaceDivision(state, action.subleague_index, action.division_index, division => ({ name: action.name, id: division.id, teams: division.teams })); case 'remove_team': return replaceDivision(state, action.subleague_index, action.division_index, division => ({ name: division.name, id: division.id, teams: removeIndex(division.teams, division.teams.findIndex(val => val.name === action.name)) })); case 'add_team': return replaceDivision(state, action.subleague_index, action.division_index, division => ({ name: division.name, id: division.id, teams: division.teams.concat([{ name: action.name, id: getUID() }]) })); } } function replaceSubleague(state: LeagueStructureState, si: number, func: (val: SubleagueState) => SubleagueState) { return {subleagues: replaceIndex(state.subleagues, si, func(state.subleagues[si]))} } function replaceDivision(state: LeagueStructureState, si: number, di: number, func:(val: DivisionState) => DivisionState) { return replaceSubleague(state, si, subleague => ({ name: subleague.name, id: subleague.id, divisions: replaceIndex(subleague.divisions, di, func(subleague.divisions[di])) })) } function removeIndex(arr: any[], index: number) { return arr.slice(0, index).concat(arr.slice(index+1)); } function replaceIndex(arr: T[], index: number, val: T) { return arr.slice(0, index).concat([val]).concat(arr.slice(index+1)); } function append(arr: T[], val: T) { return arr.concat([val]); } function arrayOf(length: number, func: (i: number) => T): T[] { var out: T[] = []; for (var i = 0; i < length; i++) { out.push(func(i)); } return out; } let initLeagueStructure = { subleagues: [0, 1].map((val) => ({ name: "", id: getUID(), divisions: [0, 1].map((val) => ({ name: "", id: getUID(), teams: [] })) })) } function CreateLeague() { let [name, setName] = useState(""); let [structure, dispatch] = useReducer(leagueStructureReducer, initLeagueStructure); let self = useRef(null) useLayoutEffect(() => { if (self.current) { twemoji.parse(self.current) } }) return (
setName(e.target.value)}/>
); } function LeagueStructre(props: {state: LeagueStructureState, dispatch: React.Dispatch}) { return (
); } function SubleagueHeaders(props: {subleagues: SubleagueState[], dispatch: React.Dispatch}) { return (
{props.subleagues.map((subleague, i) => (
1} dispatch={action => props.dispatch(Object.assign({subleague_index: i}, action)) }/>
))}
); } function SubleageHeader(props: {state: SubleagueState, canDelete: boolean, dispatch:(action: DistributiveOmit) => void}) { return (
props.dispatch({type: 'rename_subleague', name: e.target.value}) }/> {props.canDelete ? : null}
); } function Divisions(props: {subleagues: SubleagueState[], dispatch: React.Dispatch}) { return (<> {props.subleagues[0].divisions.map((val, di) => (
{props.subleagues[0].divisions.length > 1 ? : null }
{props.subleagues.map((subleague, si) => (
props.dispatch(Object.assign({subleague_index: si, division_index: di}, action)) }/>
))}
))} ); } function Division(props: {state: DivisionState, dispatch:(action: DistributiveOmit) => void}) { let [newName, setNewName] = useState(""); let [searchResults, setSearchResults] = useState([]); let newNameInput = useRef(null); let resultList = useRef(null); useLayoutEffect(() => { if (resultList.current) { twemoji.parse(resultList.current) } }) return (
props.dispatch({type: 'rename_division', name: e.target.value}) }/> {props.state.teams.map((team, i) => (
{team.name}
))}
{ let params = new URLSearchParams({query: e.target.value, page_len: '5', page_num: '0'}); $.getJSON("/api/teams/search?" + params.toString(), data => { console.log(data); setSearchResults(data); }) setNewName(e.target.value); }}/>
{searchResults.length > 0 && newName.length > 0 ? (
{searchResults.map(result =>
{ props.dispatch({type:'add_team', name: result}); setNewName(""); if (newNameInput.current) { newNameInput.current.focus(); } }}>{result}
)}
):
}
); } function LeagueOptions() { return (
); } export default CreateLeague;