11<script setup lang="ts">
2- import {computed } from " vue" ;
2+ import {computed , inject } from " vue" ;
33import GameEventItem from " @/components/match/GameEventItem.vue" ;
44import GameEventProposalGroupItem from " @/components/match/GameEventProposalGroupItem.vue" ;
55import {useMatchStateStore } from " @/store/matchState" ;
66import type {ProposalGroup } from " @/proto/ssl_gc_state" ;
77import type {GameEvent } from " @/proto/ssl_gc_game_event" ;
8+ import GameEventDetailsTree from " @/components/match/GameEventDetailsTree.vue" ;
9+ import type {ControlApi } from " @/providers/controlApi/ControlApi" ;
810
911const store = useMatchStateStore ()
12+ const control = inject <ControlApi >(' control-api' )
1013
1114type GameEventWrappedItem = {
1215 id: string
@@ -15,6 +18,18 @@ type GameEventWrappedItem = {
1518 gameEvent? : GameEvent
1619}
1720
21+ interface GameEventTreeNode {
22+ id: string
23+ header: string
24+ proposalGroup? : ProposalGroup
25+ gameEvent? : GameEvent
26+ children? : GameEventTreeNode []
27+ }
28+
29+ interface Prop {
30+ node: GameEventTreeNode
31+ }
32+
1833const gameEventItems = computed (() => {
1934 const gameEvents = store .matchState .gameEvents !
2035 const proposalGroups = store .matchState .proposalGroups !
@@ -46,25 +61,109 @@ const gameEventItems = computed(() => {
4661 return items
4762})
4863
64+ function gameEventNode(gameEvent : GameEvent ): GameEventTreeNode {
65+ return {
66+ id: gameEvent .id || ' ' ,
67+ header: ' game-event' ,
68+ gameEvent: gameEvent ,
69+ children: [
70+ {
71+ id: (gameEvent .id || ' ' ) + " -details" ,
72+ header: ' game-event-details' ,
73+ gameEvent: gameEvent ,
74+ }
75+ ]
76+ }
77+ }
78+
79+ const nodes = computed (() => {
80+ const nodeList: GameEventTreeNode [] = []
81+
82+ for (const gameEventItem of gameEventItems .value ) {
83+ if (gameEventItem .proposalGroup ) {
84+ let children = gameEventItem .proposalGroup .proposals ! .map (proposal => {
85+ return gameEventNode (proposal .gameEvent ! )
86+ });
87+ if (! gameEventItem .proposalGroup .accepted ) {
88+ children .unshift ({
89+ id: gameEventItem .id + " -accept" ,
90+ header: ' accept' ,
91+ proposalGroup: gameEventItem .proposalGroup ,
92+ gameEvent: gameEventItem .gameEvent ,
93+ })
94+ }
95+ nodeList .push ({
96+ id: gameEventItem .id ,
97+ header: ' proposal' ,
98+ gameEvent: gameEventItem .gameEvent ,
99+ proposalGroup: gameEventItem .proposalGroup ,
100+ children: children
101+ })
102+ } else if (gameEventItem .gameEvent ) {
103+ nodeList .push (gameEventNode (gameEventItem .gameEvent ))
104+ }
105+ }
106+ return nodeList
107+ })
108+
109+ const acceptGroup = (groupId : string ) => {
110+ control ?.AcceptProposalGroup (groupId )
111+ }
112+
49113 </script >
50114
51115<template >
52- <q-list bordered class =" rounded-borders" v-if =" gameEventItems.length > 0" >
53- <template v-for =" (item ) in gameEventItems " >
116+ <q-tree
117+ v-if =" gameEventItems.length > 0"
118+ :nodes =" nodes"
119+ node-key =" id"
120+ dense
121+ class =" full-width"
122+ >
123+ <!-- suppress VueUnrecognizedSlot -->
124+ <template #header-accept =" prop : Prop " >
125+ <q-item class =" full-width" >
126+ <q-item-section side >
127+ <q-icon name =" done" />
128+ </q-item-section >
129+ <q-item-section >
130+ <q-btn
131+ dense
132+ color =" primary"
133+ label =" Accept"
134+ @click =" () => acceptGroup(prop.node.proposalGroup?.id!)"
135+ v-if =" !prop.node.proposalGroup?.accepted" />
136+ </q-item-section >
137+ </q-item >
138+ </template >
139+
140+ <!-- suppress VueUnrecognizedSlot -->
141+ <template #header-proposal =" prop : Prop " >
54142 <GameEventProposalGroupItem
55- v-if =" item.proposalGroup"
56- :proposal-group =" item.proposalGroup"
57- :group-id =" item.id"
58- :accepted-game-event =" item.gameEvent"
59- :key =" item.id"
143+ class =" full-width"
144+ :proposal-group =" prop.node.proposalGroup!"
145+ :group-id =" prop.node.id"
146+ :accepted-game-event =" prop.node.gameEvent!"
60147 />
148+ </template >
149+
150+ <!-- suppress VueUnrecognizedSlot -->
151+ <template #header-game-event =" prop : Prop " >
61152 <GameEventItem
62- v-else-if =" item.gameEvent"
63- :game-event =" item.gameEvent"
64- :key =" item.id"
153+ class =" full-width"
154+ :game-event =" prop.node.gameEvent!"
65155 />
66156 </template >
67- </q-list >
157+
158+ <!-- suppress VueUnrecognizedSlot -->
159+ <template v-slot :header-game-event-details =" prop : Prop " >
160+ <GameEventDetailsTree
161+ class =" full-width"
162+ :game-event =" prop.node.gameEvent!"
163+ />
164+ </template >
165+ </q-tree >
166+
68167 <div v-else >
69168 No recent game event proposals
70169 </div >
0 commit comments