diff --git a/main.js b/main.js index 4086d7b..c816566 100644 --- a/main.js +++ b/main.js @@ -5334,14 +5334,14 @@ var $elm$core$Task$perform = F2( A2($elm$core$Task$map, toMessage, task))); }); var $elm$browser$Browser$application = _Browser_application; -var $author$project$Main$Model = F7( - function (state, player, claims, notification, loot, groupLoot, merchantItems) { - return {claims: claims, groupLoot: groupLoot, loot: loot, merchantItems: merchantItems, notification: notification, player: player, state: state}; +var $author$project$Main$Model = F8( + function (state, player, chest, claims, notification, loot, groupLoot, merchantItems) { + return {chest: chest, claims: claims, groupLoot: groupLoot, loot: loot, merchantItems: merchantItems, notification: notification, player: player, state: state}; }); -var $author$project$Main$PlayerChest = {$: 'PlayerChest'}; -var $author$project$Main$State = F6( - function (navKey, route, error, menuOpen, selection, activeMode) { - return {activeMode: activeMode, error: error, menuOpen: menuOpen, navKey: navKey, route: route, selection: selection}; +var $author$project$Route$PlayerChest = {$: 'PlayerChest'}; +var $author$project$Main$State = F5( + function (navKey, route, error, menuOpen, activeMode) { + return {activeMode: activeMode, error: error, menuOpen: menuOpen, navKey: navKey, route: route}; }); var $author$project$Api$Player = F4( function (id, name, debt, wealth) { @@ -6285,10 +6285,77 @@ var $author$project$Main$fetchInitialData = function (playerId) { $author$project$Api$fetchLoot($author$project$Api$OfGroup)) ])); }; +var $author$project$Chest$init = {items: _List_Nil, selection: $elm$core$Maybe$Nothing}; +var $author$project$Route$GroupLoot = {$: 'GroupLoot'}; +var $author$project$Route$Merchant = {$: 'Merchant'}; +var $author$project$Route$NewLoot = {$: 'NewLoot'}; +var $elm$url$Url$Parser$Parser = function (a) { + return {$: 'Parser', a: a}; +}; var $elm$url$Url$Parser$State = F5( function (visited, unvisited, params, frag, value) { return {frag: frag, params: params, unvisited: unvisited, value: value, visited: visited}; }); +var $elm$url$Url$Parser$mapState = F2( + function (func, _v0) { + var visited = _v0.visited; + var unvisited = _v0.unvisited; + var params = _v0.params; + var frag = _v0.frag; + var value = _v0.value; + return A5( + $elm$url$Url$Parser$State, + visited, + unvisited, + params, + frag, + func(value)); + }); +var $elm$url$Url$Parser$map = F2( + function (subValue, _v0) { + var parseArg = _v0.a; + return $elm$url$Url$Parser$Parser( + function (_v1) { + var visited = _v1.visited; + var unvisited = _v1.unvisited; + var params = _v1.params; + var frag = _v1.frag; + var value = _v1.value; + return A2( + $elm$core$List$map, + $elm$url$Url$Parser$mapState(value), + parseArg( + A5($elm$url$Url$Parser$State, visited, unvisited, params, frag, subValue))); + }); + }); +var $elm$core$List$append = F2( + function (xs, ys) { + if (!ys.b) { + return xs; + } else { + return A3($elm$core$List$foldr, $elm$core$List$cons, ys, xs); + } + }); +var $elm$core$List$concat = function (lists) { + return A3($elm$core$List$foldr, $elm$core$List$append, _List_Nil, lists); +}; +var $elm$core$List$concatMap = F2( + function (f, list) { + return $elm$core$List$concat( + A2($elm$core$List$map, f, list)); + }); +var $elm$url$Url$Parser$oneOf = function (parsers) { + return $elm$url$Url$Parser$Parser( + function (state) { + return A2( + $elm$core$List$concatMap, + function (_v0) { + var parser = _v0.a; + return parser(state); + }, + parsers); + }); +}; var $elm$url$Url$Parser$getFirstMatch = function (states) { getFirstMatch: while (true) { @@ -6404,72 +6471,6 @@ var $elm$url$Url$Parser$parse = F2( url.fragment, $elm$core$Basics$identity))); }); -var $author$project$Main$GroupLoot = {$: 'GroupLoot'}; -var $author$project$Main$Merchant = {$: 'Merchant'}; -var $author$project$Main$NewLoot = {$: 'NewLoot'}; -var $elm$url$Url$Parser$Parser = function (a) { - return {$: 'Parser', a: a}; -}; -var $elm$url$Url$Parser$mapState = F2( - function (func, _v0) { - var visited = _v0.visited; - var unvisited = _v0.unvisited; - var params = _v0.params; - var frag = _v0.frag; - var value = _v0.value; - return A5( - $elm$url$Url$Parser$State, - visited, - unvisited, - params, - frag, - func(value)); - }); -var $elm$url$Url$Parser$map = F2( - function (subValue, _v0) { - var parseArg = _v0.a; - return $elm$url$Url$Parser$Parser( - function (_v1) { - var visited = _v1.visited; - var unvisited = _v1.unvisited; - var params = _v1.params; - var frag = _v1.frag; - var value = _v1.value; - return A2( - $elm$core$List$map, - $elm$url$Url$Parser$mapState(value), - parseArg( - A5($elm$url$Url$Parser$State, visited, unvisited, params, frag, subValue))); - }); - }); -var $elm$core$List$append = F2( - function (xs, ys) { - if (!ys.b) { - return xs; - } else { - return A3($elm$core$List$foldr, $elm$core$List$cons, ys, xs); - } - }); -var $elm$core$List$concat = function (lists) { - return A3($elm$core$List$foldr, $elm$core$List$append, _List_Nil, lists); -}; -var $elm$core$List$concatMap = F2( - function (f, list) { - return $elm$core$List$concat( - A2($elm$core$List$map, f, list)); - }); -var $elm$url$Url$Parser$oneOf = function (parsers) { - return $elm$url$Url$Parser$Parser( - function (state) { - return A2( - $elm$core$List$concatMap, - function (_v0) { - var parser = _v0.a; - return parser(state); - }, - parsers); - }); -}; var $elm$url$Url$Parser$s = function (str) { return $elm$url$Url$Parser$Parser( function (_v0) { @@ -6501,39 +6502,45 @@ var $elm$url$Url$Parser$top = $elm$url$Url$Parser$Parser( return _List_fromArray( [state]); }); -var $author$project$Main$routeParser = $elm$url$Url$Parser$oneOf( - _List_fromArray( - [ - A2( - $elm$url$Url$Parser$map, - $author$project$Main$GroupLoot, - $elm$url$Url$Parser$s('coffre')), - A2($elm$url$Url$Parser$map, $author$project$Main$PlayerChest, $elm$url$Url$Parser$top), - A2( - $elm$url$Url$Parser$map, - $author$project$Main$Merchant, - $elm$url$Url$Parser$s('marchand')), - A2( - $elm$url$Url$Parser$map, - $author$project$Main$NewLoot, - $elm$url$Url$Parser$s('nouveau-tresor')) - ])); +var $author$project$Route$routeParser = function (url) { + return A2( + $elm$url$Url$Parser$parse, + $elm$url$Url$Parser$oneOf( + _List_fromArray( + [ + A2( + $elm$url$Url$Parser$map, + $author$project$Route$GroupLoot, + $elm$url$Url$Parser$s('coffre')), + A2($elm$url$Url$Parser$map, $author$project$Route$PlayerChest, $elm$url$Url$Parser$top), + A2( + $elm$url$Url$Parser$map, + $author$project$Route$Merchant, + $elm$url$Url$Parser$s('marchand')), + A2( + $elm$url$Url$Parser$map, + $author$project$Route$NewLoot, + $elm$url$Url$Parser$s('nouveau-tresor')) + ])), + url); +}; var $author$project$Main$init = F3( function (flags, url, key) { var route = function () { - var _v0 = A2($elm$url$Url$Parser$parse, $author$project$Main$routeParser, url); + var _v0 = $author$project$Route$routeParser(url); if (_v0.$ === 'Just') { var r = _v0.a; return r; } else { - return $author$project$Main$PlayerChest; + return $author$project$Route$PlayerChest; } }(); return _Utils_Tuple2( - A7( + A8( $author$project$Main$Model, - A6($author$project$Main$State, key, route, '', false, $elm$core$Maybe$Nothing, $elm$core$Maybe$Nothing), + A5($author$project$Main$State, key, route, '', false, $elm$core$Maybe$Nothing), $author$project$Api$blankPlayer, + $author$project$Chest$init, _List_Nil, $elm$core$Maybe$Nothing, $elm$core$Maybe$Nothing, @@ -6550,6 +6557,9 @@ var $author$project$Modes$Add = {$: 'Add'}; var $author$project$Main$ModeSwitched = function (a) { return {$: 'ModeSwitched', a: a}; }; +var $author$project$Chest$SetSelection = function (a) { + return {$: 'SetSelection', a: a}; +}; var $elm$core$List$filter = F2( function (isGood, list) { return A3( @@ -6654,7 +6664,7 @@ var $elm$core$Set$member = F2( var dict = _v0.a; return A2($elm$core$Dict$member, key, dict); }); -var $author$project$Main$itemInSelection = F2( +var $author$project$Chest$itemInSelection = F2( function (selection, item) { return A2( $elm$core$Maybe$withDefault, @@ -6664,7 +6674,6 @@ var $author$project$Main$itemInSelection = F2( $elm$core$Set$member(item.id), selection)); }); -var $elm$core$Debug$log = _Debug_log; var $elm$core$Platform$Cmd$none = $elm$core$Platform$Cmd$batch(_List_Nil); var $elm$browser$Browser$Navigation$pushUrl = _Browser_pushUrl; var $author$project$Api$GotActionResult = function (a) { @@ -6917,29 +6926,6 @@ var $author$project$Main$setNotification = F2( model, {notification: notification}); }); -var $elm$core$Set$remove = F2( - function (key, _v0) { - var dict = _v0.a; - return $elm$core$Set$Set_elm_builtin( - A2($elm$core$Dict$remove, key, dict)); - }); -var $author$project$Main$switchSelectionState = F2( - function (id, selection) { - if (selection.$ === 'Just') { - var s = selection.a; - return $elm$core$Maybe$Just( - function () { - var _v1 = A2($elm$core$Set$member, id, s); - if (_v1) { - return A2($elm$core$Set$remove, id, s); - } else { - return A2($elm$core$Set$insert, id, s); - } - }()); - } else { - return A2($elm$core$Debug$log, 'ignore switchSelectionState', $elm$core$Maybe$Nothing); - } - }); var $author$project$Main$targetItemsFor = F2( function (mode, model) { switch (mode.$) { @@ -7010,6 +6996,50 @@ var $author$project$Api$undoLastAction = function (id) { url: 'http://localhost:8088/api/players/' + ($elm$core$String$fromInt(id) + '/events/last') }); }; +var $elm$core$Debug$log = _Debug_log; +var $elm$core$Set$remove = F2( + function (key, _v0) { + var dict = _v0.a; + return $elm$core$Set$Set_elm_builtin( + A2($elm$core$Dict$remove, key, dict)); + }); +var $author$project$Chest$switchSelectionState = F2( + function (id, selection) { + if (selection.$ === 'Just') { + var s = selection.a; + return $elm$core$Maybe$Just( + function () { + var _v1 = A2($elm$core$Set$member, id, s); + if (_v1) { + return A2($elm$core$Set$remove, id, s); + } else { + return A2($elm$core$Set$insert, id, s); + } + }()); + } else { + return A2($elm$core$Debug$log, 'ignore switchSelectionState', $elm$core$Maybe$Nothing); + } + }); +var $author$project$Chest$update = F2( + function (msg, model) { + if (msg.$ === 'SwitchSelectionState') { + var id = msg.a; + return _Utils_Tuple2( + _Utils_update( + model, + { + selection: A2($author$project$Chest$switchSelectionState, id, model.selection) + }), + $elm$core$Platform$Cmd$none); + } else { + var _new = msg.a; + return _Utils_Tuple2( + _Utils_update( + model, + {selection: _new}), + $elm$core$Platform$Cmd$none); + } + }); var $author$project$Main$update = F2( function (msg, model) { update: @@ -7034,7 +7064,7 @@ var $author$project$Main$update = F2( case 'UrlChanged': var url = msg.a; var state = model.state; - var route = A2($elm$url$Url$Parser$parse, $author$project$Main$routeParser, url); + var route = $author$project$Route$routeParser(url); if (route.$ === 'Just') { var page = route.a; return A2( @@ -7067,6 +7097,15 @@ var $author$project$Main$update = F2( model, {player: $author$project$Api$blankPlayer}), $author$project$Main$initPlayer(newId)); + case 'ChestMsg': + var chestMsg = msg.a; + var _v4 = A2($author$project$Chest$update, chestMsg, model.chest); + var chest = _v4.a; + return _Utils_Tuple2( + _Utils_update( + model, + {chest: chest}), + $elm$core$Platform$Cmd$none); case 'ApiMsg': var apiMsg = msg.a; switch (apiMsg.$) { @@ -7179,23 +7218,6 @@ var $author$project$Main$update = F2( $elm$core$Platform$Cmd$none); } } - case 'LootViewItemSwitched': - var id = msg.a; - var state = model.state; - return _Utils_Tuple2( - _Utils_update( - model, - { - state: _Utils_update( - state, - { - selection: A2( - $elm$core$Debug$log, - 'new selection', - A2($author$project$Main$switchSelectionState, id, state.selection)) - }) - }), - $elm$core$Platform$Cmd$none); case 'ModeSwitched': var newMode = msg.a; var state = model.state; @@ -7203,46 +7225,52 @@ var $author$project$Main$update = F2( _Utils_update( model, { + chest: function () { + var _v11 = A2( + $author$project$Chest$update, + $author$project$Chest$SetSelection( + function () { + if (newMode.$ === 'Nothing') { + return $elm$core$Maybe$Nothing; + } else { + if (newMode.a.$ === 'Grab') { + var _v13 = newMode.a; + return $elm$core$Maybe$Just( + $elm$core$Set$fromList( + A2( + $elm$core$List$map, + function (c) { + return c.loot_id; + }, + model.claims))); + } else { + var others = newMode.a; + return $elm$core$Maybe$Just($elm$core$Set$empty); + } + } + }()), + model.chest); + var newChest = _v11.a; + return newChest; + }(), state: _Utils_update( state, - { - activeMode: newMode, - selection: function () { - if (newMode.$ === 'Nothing') { - return $elm$core$Maybe$Nothing; - } else { - if (newMode.a.$ === 'Grab') { - var _v11 = newMode.a; - return $elm$core$Maybe$Just( - $elm$core$Set$fromList( - A2( - $elm$core$List$map, - function (c) { - return c.loot_id; - }, - model.claims))); - } else { - var others = newMode.a; - return $elm$core$Maybe$Just($elm$core$Set$empty); - } - } - }() - }) + {activeMode: newMode}) }), $elm$core$Platform$Cmd$none); case 'ConfirmAction': - var _v12 = model.state.activeMode; - if (_v12.$ === 'Nothing') { + var _v14 = model.state.activeMode; + if (_v14.$ === 'Nothing') { var $temp$msg = $author$project$Main$ModeSwitched($elm$core$Maybe$Nothing), $temp$model = model; msg = $temp$msg; model = $temp$model; continue update; } else { - var mode = _v12.a; + var mode = _v14.a; var items = A2( $elm$core$List$filter, - $author$project$Main$itemInSelection(model.state.selection), + $author$project$Chest$itemInSelection(model.chest.selection), A2($author$project$Main$targetItemsFor, mode, model)); return _Utils_Tuple2( model, @@ -7271,6 +7299,9 @@ var $author$project$Main$update = F2( } } }); +var $author$project$Main$ChestMsg = function (a) { + return {$: 'ChestMsg', a: a}; +}; var $author$project$Main$UndoLastAction = {$: 'UndoLastAction'}; var $elm$html$Html$button = _VirtualDom_node('button'); var $elm$json$Json$Encode$string = _Json_wrap; @@ -7407,37 +7438,10 @@ var $author$project$Main$controlsWhenRoute = function (route) { } }; var $elm$html$Html$hr = _VirtualDom_node('hr'); -var $elm$core$List$any = F2( - function (isOkay, list) { - any: - while (true) { - if (!list.b) { - return false; - } else { - var x = list.a; - var xs = list.b; - if (isOkay(x)) { - return true; - } else { - var $temp$isOkay = isOkay, - $temp$list = xs; - isOkay = $temp$isOkay; - list = $temp$list; - continue any; - } - } - } - }); -var $author$project$Main$itemInClaims = F2( - function (claims, item) { - return A2( - $elm$core$List$any, - function (c) { - return _Utils_eq(c.loot_id, item.id); - }, - claims); - }); -var $author$project$Main$renderIcon = F2( +var $elm$virtual_dom$VirtualDom$map = _VirtualDom_map; +var $elm$html$Html$map = $elm$virtual_dom$VirtualDom$map; +var $elm$html$Html$section = _VirtualDom_node('section'); +var $author$project$Utils$renderIcon = F2( function (name, size) { return A2( $elm$html$Html$span, @@ -7456,17 +7460,17 @@ var $author$project$Main$renderIcon = F2( _List_Nil) ])); }); -var $author$project$Main$renderIfClaimed = F2( - function (isClaimed, item) { - var _v0 = isClaimed(item); +var $author$project$Chest$claimedItemRenderer = F2( + function (isSelected, item) { + var _v0 = isSelected(item); if (_v0) { - return A2($author$project$Main$renderIcon, 'fas fa-praying-hands', '1x'); + return A2($author$project$Utils$renderIcon, 'fas fa-praying-hands', '1x'); } else { return $elm$html$Html$text(''); } }); -var $author$project$Main$LootViewItemSwitched = function (a) { - return {$: 'LootViewItemSwitched', a: a}; +var $author$project$Chest$SwitchSelectionState = function (a) { + return {$: 'SwitchSelectionState', a: a}; }; var $author$project$Modes$canSelectIn = function (mode) { switch (mode.$) { @@ -7509,8 +7513,8 @@ var $elm$html$Html$Events$onCheck = function (tagger) { A2($elm$json$Json$Decode$map, tagger, $elm$html$Html$Events$targetChecked)); }; var $elm$html$Html$Attributes$type_ = $elm$html$Html$Attributes$stringProperty('type'); -var $author$project$Main$rowControlsForMode = F3( - function (mode, isSelected, item) { +var $author$project$Chest$rowControlsForMode = F3( + function (isSelected, mode, item) { var itemInfo = function () { switch (mode.$) { case 'Buy': @@ -7582,13 +7586,12 @@ var $author$project$Main$rowControlsForMode = F3( isSelected(item)), $elm$html$Html$Events$onCheck( function (v) { - return $author$project$Main$LootViewItemSwitched(item.id); + return $author$project$Chest$SwitchSelectionState(item.id); }) ]), _List_Nil) ]) : _List_Nil)); }); -var $elm$html$Html$section = _VirtualDom_node('section'); var $elm$html$Html$table = _VirtualDom_node('table'); var $elm$html$Html$tbody = _VirtualDom_node('tbody'); var $elm$html$Html$th = _VirtualDom_node('th'); @@ -7614,7 +7617,7 @@ var $elm$core$List$singleton = function (value) { }; var $elm$html$Html$td = _VirtualDom_node('td'); var $elm$html$Html$tr = _VirtualDom_node('tr'); -var $author$project$Main$viewItemTableRow = F3( +var $author$project$Chest$viewItemTableRow = F3( function (isSelected, rowControls, item) { return A2( $elm$html$Html$tr, @@ -7674,8 +7677,23 @@ var $author$project$Main$viewItemTableRow = F3( ])) ])); }); -var $author$project$Main$viewChest = F3( - function (isSelected, rowControls, items) { +var $author$project$Chest$view = F3( + function (mode, route, model) { + var isSelected = $author$project$Chest$itemInSelection(model.selection); + var rowControls = function () { + if (mode.$ === 'Just') { + var m = mode.a; + return $elm$core$Maybe$Just( + A2($author$project$Chest$rowControlsForMode, isSelected, m)); + } else { + if (route.$ === 'GroupLoot') { + return $elm$core$Maybe$Just( + $author$project$Chest$claimedItemRenderer(isSelected)); + } else { + return $elm$core$Maybe$Nothing; + } + } + }(); return A2( $elm$html$Html$table, _List_fromArray( @@ -7705,8 +7723,8 @@ var $author$project$Main$viewChest = F3( _List_Nil, A2( $elm$core$List$map, - A2($author$project$Main$viewItemTableRow, isSelected, rowControls), - items)) + A2($author$project$Chest$viewItemTableRow, isSelected, rowControls), + model.items)) ])); }); var $author$project$Main$stackedIcon = function (name) { @@ -7866,7 +7884,7 @@ var $author$project$Main$viewDebugSection = function (model) { _List_fromArray( [ $elm$html$Html$text( - 'Selection : ' + $elm$core$Debug$toString(model.state.selection)) + 'Selection : ' + $elm$core$Debug$toString(model.chest.selection)) ])), A2( $elm$html$Html$p, @@ -7924,7 +7942,7 @@ var $author$project$Main$viewHeaderBar = function (model) { ]), _List_fromArray( [ - A2($author$project$Main$renderIcon, 'fab fa-d-and-d', '2x'), + A2($author$project$Utils$renderIcon, 'fab fa-d-and-d', '2x'), A2( $elm$html$Html$span, _List_Nil, @@ -7989,7 +8007,7 @@ var $author$project$Main$viewHeaderBar = function (model) { ]), _List_fromArray( [ - A2($author$project$Main$renderIcon, 'fas fa-store-alt', '1x'), + A2($author$project$Utils$renderIcon, 'fas fa-store-alt', '1x'), A2( $elm$html$Html$span, _List_Nil, @@ -8008,7 +8026,7 @@ var $author$project$Main$viewHeaderBar = function (model) { ]), _List_fromArray( [ - A2($author$project$Main$renderIcon, 'fas fa-gem', '1x'), + A2($author$project$Utils$renderIcon, 'fas fa-gem', '1x'), A2( $elm$html$Html$span, _List_Nil, @@ -8230,7 +8248,18 @@ var $author$project$Main$viewSearchBar = A2( ]), _List_Nil); var $author$project$Main$view = function (model) { - var isSelected = $author$project$Main$itemInSelection(model.state.selection); + var headerControls = function () { + var _v2 = model.state.activeMode; + if (_v2.$ === 'Just') { + var mode = _v2.a; + return $author$project$Main$controlsWhenModeActive(mode); + } else { + return A2( + $elm$core$List$cons, + A4($author$project$Main$actionButton, $author$project$Main$UndoLastAction, 'Annuler action', 'backspace', 'danger'), + $author$project$Main$controlsWhenRoute(model.state.route)); + } + }(); var _v0 = function () { var _v1 = model.state.route; switch (_v1.$) { @@ -8252,34 +8281,6 @@ var $author$project$Main$view = function (model) { }(); var header = _v0.a; var shownLoot = _v0.b; - var _v2 = function () { - var _v3 = model.state.activeMode; - if (_v3.$ === 'Just') { - var mode = _v3.a; - return _Utils_Tuple2( - $author$project$Main$controlsWhenModeActive(mode), - $elm$core$Maybe$Just( - A2($author$project$Main$rowControlsForMode, mode, isSelected))); - } else { - return _Utils_Tuple2( - A2( - $elm$core$List$cons, - A4($author$project$Main$actionButton, $author$project$Main$UndoLastAction, 'Annuler action', 'backspace', 'danger'), - $author$project$Main$controlsWhenRoute(model.state.route)), - function () { - var _v4 = model.state.route; - if (_v4.$ === 'GroupLoot') { - return $elm$core$Maybe$Just( - $author$project$Main$renderIfClaimed( - $author$project$Main$itemInClaims(model.claims))); - } else { - return $elm$core$Maybe$Nothing; - } - }()); - } - }(); - var headerControls = _v2.a; - var rowControls = _v2.b; return { body: _List_fromArray( [ @@ -8293,6 +8294,7 @@ var $author$project$Main$view = function (model) { ]), _List_fromArray( [ + $author$project$Main$viewNotification(model.notification), A2( $elm$html$Html$p, _List_fromArray( @@ -8304,7 +8306,10 @@ var $author$project$Main$view = function (model) { $elm$html$Html$text(header) ])), $author$project$Main$viewSearchBar, - A3($author$project$Main$viewChest, isSelected, rowControls, shownLoot) + A2( + $elm$html$Html$map, + $author$project$Main$ChestMsg, + A3($author$project$Chest$view, model.state.activeMode, model.state.route, model.chest)) ])), A2($elm$html$Html$hr, _List_Nil, _List_Nil), A2( diff --git a/src/Chest.elm b/src/Chest.elm new file mode 100644 index 0000000..129cff2 --- /dev/null +++ b/src/Chest.elm @@ -0,0 +1,112 @@ +module Chest exposing (..) + +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (onCheck) +import Set exposing (Set) + +import Route +import Modes exposing (ViewMode) +import Api exposing (Item) +import Utils exposing (..) + +type alias Model = + { items: List Item + , selection : Maybe Selection + } + +type alias Selection = Set Int + +type Msg + = SetSelection (Maybe Selection) + | SwitchSelectionState Int + +init : Model +init = + { items = [] + , selection = Nothing + } + +update : Msg -> Model -> (Model, Cmd Msg) +update msg model = + case msg of + SwitchSelectionState id -> + ( { model | selection = switchSelectionState id model.selection }, Cmd.none ) + + SetSelection new -> + ( { model | selection = new }, Cmd.none ) + +view : Maybe ViewMode -> Route.Route -> Model -> Html Msg +view mode route model = + let + isSelected = itemInSelection model.selection + rowControls = case mode of + Just m -> + Just (rowControlsForMode isSelected m) + Nothing -> -- Claim controls for Group chest + case route of + Route.GroupLoot -> Just (claimedItemRenderer isSelected) + _ -> Nothing + + in + table [ class "table is-fullwidth is-hoverable"] + [ thead [ class "table-header" ] + [ th [] [ text "Nom" ] ] + , tbody [] <| List.map (viewItemTableRow isSelected rowControls) model.items + ] + +claimedItemRenderer isSelected item = + case isSelected item of + True -> renderIcon "fas fa-praying-hands" "1x" + False -> text "" + + +-- Renders controls for a specific mode +rowControlsForMode : (Item -> Bool) -> ViewMode -> Item -> Html Msg +rowControlsForMode isSelected mode item = + let + itemInfo = case mode of + Modes.Buy -> p [class "level-item"] [ text (String.fromInt item.base_price ++ "po")] + Modes.Sell -> p [class "level-item"] [ text (String.fromFloat (toFloat item.base_price / 2) ++ "po")] + Modes.Grab -> p [class "level-item"] [ text "Grab" ] + Modes.Add -> p [class "level-item"] [ text "New !" ] + in + div [ class "level-right" ] + <| itemInfo + :: if Modes.canSelectIn mode then + [input [ class "checkbox level-item" + , type_ "checkbox" + , checked <| isSelected item + , onCheck (\v -> SwitchSelectionState item.id) + ] [] ] + else + [] + + +viewItemTableRow : (Item -> Bool) -> Maybe (Item -> Html Msg) -> Item -> Html Msg +viewItemTableRow isSelected rowControls item = + tr [ classList [ ("is-selected", isSelected item) ] ] + [ td [] + [ label [ class "level checkbox" ] + <| div [ class "level-left" ] + [ p [class "level-item"] [ text item.name ]] + :: case rowControls of + Just render -> List.singleton (render item) + Nothing -> [] + ] + ] + +itemInSelection : Maybe Selection -> Item -> Bool +itemInSelection selection item = + Maybe.map (Set.member item.id) selection + |> Maybe.withDefault False + + +switchSelectionState : Int -> Maybe Selection -> Maybe Selection +switchSelectionState id selection = + case selection of + Just s -> + Just <| case Set.member id s of + True -> Set.remove id s + False -> Set.insert id s + Nothing -> Debug.log "ignore switchSelectionState" Nothing diff --git a/src/Main.elm b/src/Main.elm index 0344ac3..638b4e6 100644 --- a/src/Main.elm +++ b/src/Main.elm @@ -7,13 +7,15 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (..) import Svg.Attributes -import Url.Parser as P exposing (Parser, (), oneOf, s) import Set exposing (Set) import Json.Encode as E import Api exposing (Player, Loot, Wealth, Item, Claim, Claims) import Modes exposing (ViewMode) - +import Route exposing (..) +import Chest +import Chest exposing (Msg) +import Utils exposing (..) -- Main main : Program () Model Msg @@ -29,20 +31,19 @@ main = -- Model -type alias Selection = Set Int type alias State = { navKey : Nav.Key , route : Route , error : String , menuOpen : Bool - , selection : Maybe Selection , activeMode : Maybe ViewMode } type alias Model = { state : State , player: Player + , chest : Chest.Model , claims : Claims , notification : Maybe String , loot: Maybe Loot @@ -53,13 +54,14 @@ type alias Model = init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg ) init flags url key = let - route = case P.parse routeParser url of + route = case routeParser url of Just r -> r Nothing -> PlayerChest in ( Model - (State key route "" False Nothing Nothing) + (State key route "" False Nothing) Api.blankPlayer + Chest.init [] Nothing Nothing @@ -89,8 +91,8 @@ type Msg = LinkClicked Browser.UrlRequest | UrlChanged Url.Url | ApiMsg Api.Msg + | ChestMsg Chest.Msg | PlayerChanged Int - | LootViewItemSwitched Int | ModeSwitched (Maybe ViewMode) | ConfirmAction | UndoLastAction @@ -110,7 +112,7 @@ update msg model = UrlChanged url -> let - route = P.parse routeParser url + route = routeParser url state = model.state in case route of @@ -128,6 +130,12 @@ update msg model = PlayerChanged newId -> ( { model | player = Api.blankPlayer }, initPlayer newId ) + ChestMsg chestMsg -> + let + (chest, _) = Chest.update chestMsg model.chest + in + ( { model | chest = chest }, Cmd.none ) + ApiMsg apiMsg -> case apiMsg of Api.GotActionResult response -> case response of @@ -173,32 +181,28 @@ update msg model = , Cmd.none ) - LootViewItemSwitched id -> - let - state = model.state - in - ( { model | state = - { state | selection = Debug.log "new selection" - <| switchSelectionState id state.selection }} - , Cmd.none ) - ModeSwitched newMode -> let state = model.state in ( { model | state = - { state | activeMode = newMode - , selection = - case newMode of - Nothing -> - Nothing + { state | activeMode = newMode } + , chest = + let + (newChest, _) = Chest.update (Chest.SetSelection + (case newMode of + Nothing -> + Nothing - Just Modes.Grab -> -- Currently claimed object are initially selected - Just ( Set.fromList <| List.map (\c -> c.loot_id) model.claims) + Just Modes.Grab -> -- Currently claimed object are initially selected + Just ( Set.fromList <| List.map (\c -> c.loot_id) model.claims) - Just others -> - Just Set.empty - }} + Just others -> + Just Set.empty + )) + model.chest + in newChest + } , Cmd.none ) ConfirmAction -> @@ -208,7 +212,7 @@ update msg model = Just mode -> let items = targetItemsFor mode model - |> List.filter (itemInSelection model.state.selection) + |> List.filter (Chest.itemInSelection model.chest.selection) in ( model , Cmd.map ApiMsg @@ -274,15 +278,6 @@ setError error model = -- STATE Utils -switchSelectionState : Int -> Maybe Selection -> Maybe Selection -switchSelectionState id selection = - case selection of - Just s -> - Just <| case Set.member id s of - True -> Set.remove id s - False -> Set.insert id s - Nothing -> Debug.log "ignore switchSelectionState" Nothing - -- SUBSCRIPTIONS -- subscriptions : Model -> Sub Msg @@ -335,33 +330,28 @@ view model = Header controls are inserted in the PlayerBar and rowControls to the right side of every item rows -} - (headerControls, rowControls) = + headerControls = case model.state.activeMode of - Just mode -> - ( controlsWhenModeActive mode, Just (rowControlsForMode mode isSelected)) + Just mode -> controlsWhenModeActive mode Nothing -> -- Buttons to enter mode - ( actionButton UndoLastAction "Annuler action" "backspace" "danger" - :: controlsWhenRoute model.state.route - -- Claim controls for Group chest - , case model.state.route of - GroupLoot -> Just (renderIfClaimed <| itemInClaims model.claims) - _ -> Nothing - ) - - -- TODO: should we extract the Maybe conversion - -- and represent cannotSelect with Nothing ?? - isSelected = - itemInSelection model.state.selection + actionButton UndoLastAction "Annuler action" "backspace" "danger" + :: controlsWhenRoute model.state.route in { title = "Loot-a-lot in ELM" , body = [ viewHeaderBar model , viewPlayerBar model.player model.notification headerControls - , article [class "section container"] - [ p [class "heading"] [text header] - , viewSearchBar - , viewChest isSelected rowControls shownLoot - ] + , article + [ class "section container" ] + [ viewNotification model.notification + , p [class "heading"] [text header] + , viewSearchBar + , Chest.view + model.state.activeMode + model.state.route + model.chest + |> Html.map ChestMsg + ] , hr [] [] , section [class "container"] [viewDebugSection model] ] @@ -377,64 +367,10 @@ viewNotification notification = -- LOOT Views -itemInSelection : Maybe Selection -> Item -> Bool -itemInSelection selection item = - Maybe.map (Set.member item.id) selection - |> Maybe.withDefault False - itemInClaims : List Claim -> Item -> Bool itemInClaims claims item = List.any (\c -> c.loot_id == item.id) claims -renderIfClaimed : (Item -> Bool) -> Item -> Html Msg -renderIfClaimed isClaimed item = - case isClaimed item of - True -> renderIcon "fas fa-praying-hands" "1x" - False -> text "" - -viewChest : (Item -> Bool) -> Maybe (Item -> Html Msg) -> Loot -> Html Msg -viewChest isSelected rowControls items = - table [ class "table is-fullwidth is-hoverable"] - [ thead [ class "table-header" ] - [ th [] [ text "Nom" ] ] - , tbody [] <| List.map (viewItemTableRow isSelected rowControls) items - ] - --- Renders controls for a specific mode -rowControlsForMode : ViewMode -> (Item -> Bool) -> Item -> Html Msg -rowControlsForMode mode isSelected item = - let - itemInfo = case mode of - Modes.Buy -> p [class "level-item"] [ text (String.fromInt item.base_price ++ "po")] - Modes.Sell -> p [class "level-item"] [ text (String.fromFloat (toFloat item.base_price / 2) ++ "po")] - Modes.Grab -> p [class "level-item"] [ text "Grab" ] - Modes.Add -> p [class "level-item"] [ text "New !" ] - in - div [ class "level-right" ] - <| itemInfo - :: if Modes.canSelectIn mode then - [input [ class "checkbox level-item" - , type_ "checkbox" - , checked <| isSelected item - , onCheck (\v -> LootViewItemSwitched item.id) - ] [] ] - else - [] - - -viewItemTableRow : (Item -> Bool) -> Maybe (Item -> Html Msg) -> Item -> Html Msg -viewItemTableRow isSelected rowControls item = - tr [ classList [ ("is-selected", isSelected item) ] ] - [ td [] - [ label [ class "level checkbox" ] - <| div [ class "level-left" ] - [ p [class "level-item"] [ text item.name ]] - :: case rowControls of - Just render -> List.singleton (render item) - Nothing -> [] - ] - ] - -- DEBUG SECTION viewDebugSection : Model -> Html Msg @@ -445,7 +381,7 @@ viewDebugSection model = , p [class "panel-block has-text-danger"] [text model.state.error] , p [class "panel-block"] [text ("Route : " ++ Debug.toString model.state.route)] , p [class "panel-block"] [text ("Active Mode : " ++ Debug.toString model.state.activeMode)] - , p [class "panel-block"] [text ("Selection : " ++ Debug.toString model.state.selection)] + , p [class "panel-block"] [text ("Selection : " ++ Debug.toString model.chest.selection)] , p [class "panel-block"] [text ("Claims : " ++ Debug.toString model.claims)] , p [] debugSandbox ] @@ -483,10 +419,6 @@ debugSwitchPlayers = ] -renderIcon name size = - span [ class <| "icon is-medium"] - [ i [ class <| name ++ " fa-" ++ size] [] ] - -- HEADER SECTION @@ -572,23 +504,3 @@ showWealthField name value = viewSearchBar : Html Msg viewSearchBar = input [class "input"] [] - ---- --- ROUTES ---- - -type Route - = PlayerChest - | Merchant - | GroupLoot - | NewLoot - -routeParser : Parser (Route -> a) a -routeParser = - oneOf - [ P.map GroupLoot (P.s "coffre") - , P.map PlayerChest P.top - , P.map Merchant (P.s "marchand") - , P.map NewLoot (P.s "nouveau-tresor") - ] - diff --git a/src/Route.elm b/src/Route.elm new file mode 100644 index 0000000..446d162 --- /dev/null +++ b/src/Route.elm @@ -0,0 +1,25 @@ +module Route exposing(..) + +import Url +import Url.Parser as P exposing (Parser, (), oneOf, s) +--- +-- ROUTES +--- + +type Route + = PlayerChest + | Merchant + | GroupLoot + | NewLoot + +routeParser : Url.Url -> Maybe Route +routeParser url = + P.parse + (oneOf + [ P.map GroupLoot (P.s "coffre") + , P.map PlayerChest P.top + , P.map Merchant (P.s "marchand") + , P.map NewLoot (P.s "nouveau-tresor") + ] + ) + url diff --git a/src/Utils.elm b/src/Utils.elm new file mode 100644 index 0000000..18b648a --- /dev/null +++ b/src/Utils.elm @@ -0,0 +1,8 @@ +module Utils exposing (renderIcon) + +import Html exposing (..) +import Html.Attributes exposing (..) + +renderIcon name size = + span [ class <| "icon is-medium"] + [ i [ class <| name ++ " fa-" ++ size] [] ]