Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 37 additions & 3 deletions src/App.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,44 @@
open Feliz
open Browser.Dom
open Fable.Core.JsInterop

open Feliz.Router

importSideEffects "./index.css"


let root = ReactDOM.createRoot(document.getElementById "root")
root.render(App.Components.Counter())

let menu =
Html.div [
Html.a [
prop.href (Router.formatPath [])
prop.text "Home"
]
Html.a [
prop.href (Router.formatPath ["login"])
prop.text "Login"
]
]

let homePage =
Html.div [
menu
App.Components.Counter()
]

let loginPage =
Html.div [
menu
App.Components.MaterialUiLogin()
]

let app =
React.router [
router.onUrlChanged (fun url ->
match url with
| [] -> homePage
| ["login"] -> loginPage
| _ -> Html.h1 "Page not found"
)
]

root.render(app)
50 changes: 49 additions & 1 deletion src/Components.fs
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,52 @@ type Components() =
prop.className "read-the-docs"
prop.text " Click on the Vite, React or Fable Vite Plugin logos to learn more"
]
]
]

[<ReactComponent>]
static member MaterialUiLogin() =
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change this to just import the .tsx component

let (username, setUsername) = React.useState("")
let (password, setPassword) = React.useState("")
let (message, setMessage) = React.useState("")

let handleSubmit (e: Browser.Types.Event) =
e.preventDefault()
setMessage("Login successful!")

Html.div [
Html.h2 "Login"
Html.form [
prop.onSubmit handleSubmit
prop.children [
Html.div [
Html.label [
prop.htmlFor "username"
prop.text "Username"
]
Html.input [
prop.id "username"
prop.type' "text"
prop.value username
prop.onChange (fun (e: string) -> setUsername(e))
]
]
Html.div [
Html.label [
prop.htmlFor "password"
prop.text "Password"
]
Html.input [
prop.id "password"
prop.type' "password"
prop.value password
prop.onChange (fun (e: string) -> setPassword(e))
]
]
Html.button [
prop.type' "submit"
prop.text "Submit"
]
]
]
Html.p message
]
20 changes: 20 additions & 0 deletions src/Components.test.fs
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,23 @@ Jest.describe("Counter component", fun () ->
Jest.expect(updatedButtonElement).toBeInTheDocument()
)
)

Jest.describe("MaterialUiLogin component", fun () ->
let element = RTL.render(Components.MaterialUiLogin())

Jest.test("should render login form", fun () ->
let usernameLabel = element.getByText("Username")
let passwordLabel = element.getByText("Password")
let submitButton = element.getByText("Submit")
Jest.expect(usernameLabel).toBeInTheDocument()
Jest.expect(passwordLabel).toBeInTheDocument()
Jest.expect(submitButton).toBeInTheDocument()
)

Jest.test("should show success message on submit", fun () ->
let submitButton = element.getByText("Submit")
RTL.fireEvent.click(submitButton)
let successMessage = element.getByText("Login successful!")
Jest.expect(successMessage).toBeInTheDocument()
)
)
42 changes: 42 additions & 0 deletions src/MaterialUiLogin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React, { useState } from 'react';

const MaterialUiLogin = () => {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using tsx to define a material ui login form

const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [message, setMessage] = useState('');

const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
setMessage('Login successful!');
};

return (
<div>
<h2>Login</h2>
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="username">Username</label>
<input
id="username"
type="text"
value={username}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setUsername(e.target.value)}
/>
</div>
<div>
<label htmlFor="password">Password</label>
<input
id="password"
type="password"
value={password}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setPassword(e.target.value)}
/>
</div>
<button type="submit">Submit</button>
</form>
<p>{message}</p>
</div>
);
};

export default MaterialUiLogin;
Loading