module Pages.Debate.Arguments exposing (Model, Msg, page) import Browser.Events as Events import Config.Data.Identity exposing (pageNames) import Config.Data.ImageFolders as M exposing ( ImageFolder(..) , imagePathMaker ) import Config.Helpers.Cards.Inner.StrengthBar exposing (barMaker) import Config.Helpers.Cards.Inner.Text exposing ( bodyFormat , detailBodyLink , detailBodyMaker , detailFormat , detailSpacing , detailTitleMaker , generalButton , getHoverColours ) import Config.Helpers.Cards.Inner.ToolTip exposing (tooltip) import Config.Helpers.Cards.Outer.Helpers exposing (cardMaker) import Config.Helpers.Cards.Outer.Types as C exposing (Cardable(..)) import Config.Helpers.Converters exposing (toTitleCase) import Config.Helpers.Headers.Helpers exposing (headerMaker) import Config.Helpers.Headers.Records exposing (argumentHeader) import Config.Helpers.Headers.Types as R exposing (Headerable(..)) import Config.Helpers.Response exposing ( pageList , topLevelContainer ) import Config.Helpers.Viewport exposing (resetViewport) import Config.Pages.Debate.Arguments.List exposing ( argumentList ) import Config.Pages.Debate.Arguments.Types exposing (Argument) import Config.Style.Colour.Helpers exposing ( ThemeColor(..) , getThemeColor ) import Config.Style.Icons.Icons exposing ( code , copyLink , thumbsDown ) import Config.Style.Icons.Types as TySvg exposing ( InnerPart , OuterPart ) import Config.Style.Images exposing (imageSquareMaker) import Config.Style.Transitions exposing (transitionStyleSlow) import Effect exposing (Effect) import Element as E exposing ( Attribute , Device , DeviceClass(..) , Element , Orientation(..) , alignLeft , alignRight , alignTop , centerX , centerY , clip , column , el , fill , focused , height , htmlAttribute , maximum , none , paddingEach , paddingXY , paragraph , rgba , row , spacing , text , width ) import Element.Background as B exposing (color) import Element.Border as D exposing ( color , rounded , shadow ) import Element.Font as F exposing ( bold , center , color ) import Element.Input as Input import Html.Attributes as H exposing (style) import Layouts import Page exposing (Page) import Ports import Process import Route exposing (Route) import Route.Path as Path import Shared import Svg.Attributes as SvgAttr import Task import View exposing (View) page : Shared.Model -> Route () -> Page Model Msg page shared route = Page.new { init = init , update = update , subscriptions = subscriptions , view = view shared } |> Page.withLayout toLayout toLayout : Model -> Layouts.Layout Msg toLayout model = Layouts.Navbar {} -- INIT type alias Model = { hasBeenCopied : List Bool } init : () -> ( Model, Effect Msg ) init () = ( { hasBeenCopied = List.repeat 51 False } , Effect.batch [ Effect.map (\_ -> NoOp) (Effect.sendCmd resetViewport) , Effect.none ] ) -- UPDATE type Msg = CopyText String Int | ResetCopyState Int | NoOp update : Msg -> Model -> ( Model, Effect Msg ) update msg model = let urlLinkClickUpdate : Int -> Model urlLinkClickUpdate index = { model | hasBeenCopied = List.take index model.hasBeenCopied ++ (case List.head (List.drop index model.hasBeenCopied) of Just isCLicked -> [ not isCLicked ] Nothing -> [] -- shouldn't happen ) ++ List.drop (index + 1) model.hasBeenCopied } in case msg of CopyText text index -> ( urlLinkClickUpdate index , Effect.batch [ Effect.sendCmd (Ports.copyToClipboard text) , Effect.sendCmd (Process.sleep 700 |> Task.perform (\_ -> ResetCopyState index)) ] ) ResetCopyState index -> ( urlLinkClickUpdate index -- wrong lol , Effect.none ) NoOp -> ( model , Effect.none ) -- SUBSCRIPTIONS subscriptions : Model -> Sub Msg subscriptions model = Sub.none -- VIEW view : Shared.Model -> Model -> View Msg view shared model = { title = "debate (" ++ pageNames.pageArguments ++ ")" , attributes = [] , element = debateContainer shared model } debateContainer : Shared.Model -> Model -> Element Msg debateContainer shared model = topLevelContainer (debateList shared model) debateList : Shared.Model -> Model -> Element Msg debateList shared model = column (case ( shared.device.class, shared.device.orientation ) of _ -> pageList shared.device ) <| List.concat [ [ headerMaker (R.Arguments argumentHeader) ] , List.map3 (\argument dummy index -> cardMaker shared.device (C.Argument argument) (contentList shared model dummy index argument) ) argumentList model.hasBeenCopied (List.range 0 (List.length argumentList)) ] contentList : Shared.Model -> Model -> Bool -> Int -> Argument -> List (Element Msg) contentList shared model isLinkClicked index argument = let image : String -> Element msg image size = el [ alignLeft , alignTop , paddingEach { top = 0 , right = 10 , bottom = 0 , left = 0 } ] <| imageSquareMaker shared.device (imagePathMaker M.Argument argument.argumentImage) True size in [ row [ width fill , paddingEach { top = case ( shared.device.class, shared.device.orientation ) of ( Phone, Portrait ) -> 8 ( Tablet, Portrait ) -> 8 _ -> 0 , right = 0 , bottom = 0 , left = 0 } ] [ detailFormat column [ detailFormat paragraph [ case ( shared.device.class, shared.device.orientation ) of ( Phone, Portrait ) -> none ( Tablet, Portrait ) -> none _ -> image "Big" , el ([ height fill ] ++ bodyFormat TextLightGrey) <| text argument.propositionSummary ] , detailFormat row [ strengthMaker shared , barMaker getConfidenceTooltip argument.argumentCertainty ] ] ] , tableMaker shared.device argument , formalizationMaker shared.device argument , el [ alignRight ] <| row [ width fill, spacing 20 ] [ generalButton shared (Path.toString Path.Contact_Criticism) thumbsDown , generalButton shared argument.proofLink code , copyButton shared model isLinkClicked index argument ] ] copyButton : Shared.Model -> Model -> Bool -> Int -> Argument -> Element Msg copyButton shared model isLinkClicked index argument = Input.button [ focused [ D.color (rgba 0 0 0 0) , D.shadow { blur = 0, color = rgba 0 0 0 0, offset = ( 0, 0 ), size = 0 } ] ] { onPress = Just (CopyText ("https://uprootnutrition.com" ++ Path.toString Path.Debate_Arguments ++ "#" ++ argument.argumentImage) index) , label = el (if isLinkClicked then [ transitionStyleSlow , tooltip "Copied!" False , case ( shared.device.class, shared.device.orientation ) of ( Phone, Portrait ) -> B.color (getThemeColor BackgroundDarkGrey) ( Tablet, Portrait ) -> B.color (getThemeColor BackgroundDarkGrey) _ -> B.color (getThemeColor BackgroundDeepDarkGrey) , paddingXY 7 7 , D.rounded 10 , F.color (getThemeColor TextLightOrange) ] else [ transitionStyleSlow , B.color (getThemeColor Transparent) , paddingXY 7 7 , D.rounded 10 , F.color (getThemeColor TextLightOrange) ] ++ getHoverColours TextLightOrange ) <| copyLink { elementAttributes = [] , sharedModel = shared , svgAttributes = [ SvgAttr.width "20" ] } } strengthMaker : Shared.Model -> Element msg strengthMaker shared = el (if not shared.isNavbarExpanded then [ tooltip "This represents how pleasant the host was to engage with." True ] else [] ) <| detailTitleMaker TextLightOrange "Confidence:" getConfidenceTooltip : Int -> String getConfidenceTooltip num = case num of 0 -> "Extremely low. Speculative reasoning." 1 -> "Very low. Extremely weak reasoning." 2 -> "Low. Weak reasoning." 3 -> "Kinda low. Somewhat weak reasoning." 4 -> "Below average. More weak than strong." 5 -> "Moderate. OK reasoning." 6 -> "Above average. More strong than weak." 7 -> "Kinda high. Somewhat strong reasoning." 8 -> "High. Robust reasoning." 9 -> "Very high. Extremely robust reasoning." 10 -> "Extremely high. Air tight reasoning." _ -> "Confidence level out of expected range." tableMaker : Device -> Argument -> Element msg tableMaker device argument = let cellPadding : Attribute msg cellPadding = paddingXY 10 5 in column [ centerX , E.width fill ] [ el [ E.width fill , htmlAttribute <| H.style "position" "relative" ] <| E.table ([ D.rounded 10 , D.width 2 , D.color (getThemeColor TextDarkGrey) , clip ] ++ (case ( device.class, device.orientation ) of ( Phone, Portrait ) -> [ B.color (getThemeColor BackgroundSpreadsheet) ] ( Tablet, Portrait ) -> [ B.color (getThemeColor BackgroundSpreadsheet) ] _ -> [] ) ) { data = argument.definitionTable , columns = [ { header = el [ F.bold , D.widthEach { bottom = 1 , top = 1 , left = 1 , right = 1 } , D.color (getThemeColor TextDarkGrey) , cellPadding , E.width fill ] <| detailTitleMaker TextLightOrange "Definiendum" , width = fill |> maximum 30 , view = \definition -> el [ D.widthEach { bottom = 1 , top = 0 , left = 1 , right = 1 } , D.color (getThemeColor TextDarkGrey) , cellPadding , E.height fill ] <| el [ centerX , centerY ] <| paragraph [] [ detailTitleMaker TextLightOrange definition.definiendum ] } , { header = el [ D.widthEach { bottom = 1 , top = 1 , left = 0 , right = 1 } , D.color (getThemeColor TextDarkGrey) , cellPadding , E.width fill ] <| detailTitleMaker TextLightOrange "Definiens" , width = fill , view = \definition -> el [ D.widthEach { bottom = 1 , top = 0 , left = 0 , right = 1 } , D.color (getThemeColor TextDarkGrey) , cellPadding , E.height fill ] <| el [] <| paragraph [] [ detailBodyMaker TextLightGrey (text definition.definiens) ] } ] } ] formalizationMaker : Device -> Argument -> Element msg formalizationMaker device argument = column [ centerX , E.width fill , spacing 10 ] (List.indexedMap (\index argumentEntry -> column [ paddingXY (case ( device.class, device.orientation ) of ( Phone, Portrait ) -> 0 ( Tablet, Portrait ) -> 0 _ -> 40 ) 3 ] (List.indexedMap (\entryIndex entryWithNotation -> column [ centerX , F.center , detailSpacing , E.width fill ] [ paragraph [ width fill ] [ detailTitleMaker TextLightOrange (if entryIndex < List.length argumentEntry.premises then "P" ++ String.fromInt (entryIndex + 1) ++ ") " else "C) " ) , detailBodyMaker TextLightGrey (text (if entryIndex < List.length argumentEntry.premises then entryWithNotation.premise else argumentEntry.conclusion ) ) |> el [] ] , paragraph [] [ detailTitleMaker TextLightOrange (if entryIndex < List.length argumentEntry.premises then "(" ++ entryWithNotation.notation ++ ")" else "(∴" ++ argumentEntry.conclusionNotation ++ ")" ) ] ] ) (argumentEntry.premises ++ [ { premise = argumentEntry.conclusion, notation = argumentEntry.conclusionNotation } ]) ) ) argument.argumentFormalization )