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 ( ToolTipPosition(..) , 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 ( ElementSize(..) , 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 (List.length argumentList) 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 : ElementSize -> 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 Medium , el ([ height fill ] ++ bodyFormat TextLightGrey) <| text argument.propositionSummary ] , detailFormat row [ strengthMaker shared , barMaker shared 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 IsRight "Copied!" , 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 (case ( shared.device.class, shared.device.orientation ) of ( Phone, Portrait ) -> [] ( Tablet, Portrait ) -> [] _ -> if not shared.isNavbarExpanded then [ tooltip IsLeft "This represents how dope I think the inference/reductio is." ] else [] ) <| detailTitleMaker TextLightOrange "Banger Rating:" getConfidenceTooltip : Int -> String getConfidenceTooltip num = case num of 0 -> "Extremely low. Highly speculative." 1 -> "Very low. Almost entirely uncertain." 2 -> "Low. Highly uncertain." 3 -> "Kinda low. More uncertain than not." 4 -> "Below average. Some significant doubts." 5 -> "Moderate. Equal mix of certainty and doubt." 6 -> "Above average. More certain than not." 7 -> "Kinda high. Fairly confident." 8 -> "High. Strongly confident." 9 -> "Very high. Almost entirely certain." 10 -> "Extremely high. Completely certain." _ -> "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 )