Skip to content

Commit 7d21558

Browse files
25 - Decouple the Contact Page State & Model
1 parent 768c30e commit 7d21558

File tree

8 files changed

+158
-143
lines changed

8 files changed

+158
-143
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from .form import contact_form
2+
from .state import ContactState
3+
from .page import contact_page
4+
5+
__all__ = [
6+
'contact_form',
7+
'ContactState',
8+
'contact_page'
9+
]

full_stack_python/contact/form.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import reflex as rx
2+
3+
4+
from .state import ContactState
5+
6+
def contact_form() -> rx.Component:
7+
return rx.form(
8+
rx.vstack(
9+
rx.hstack(
10+
rx.input(
11+
name="first_name",
12+
placeholder="First Name",
13+
required=True,
14+
type='text',
15+
width='100%',
16+
),
17+
rx.input(
18+
name="last_name",
19+
placeholder="Last Name",
20+
type='text',
21+
width='100%',
22+
),
23+
width='100%'
24+
),
25+
rx.input(
26+
name='email',
27+
placeholder='Your email',
28+
type='email',
29+
width='100%',
30+
),
31+
rx.text_area(
32+
name='message',
33+
placeholder="Your message",
34+
required=True,
35+
width='100%',
36+
),
37+
rx.button("Submit", type="submit"),
38+
),
39+
on_submit=ContactState.handle_submit,
40+
reset_on_submit=True,
41+
)

full_stack_python/contact/model.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from datetime import datetime, timezone
2+
3+
import asyncio
4+
import reflex as rx
5+
6+
import sqlalchemy
7+
from sqlmodel import Field
8+
9+
10+
def get_utc_now() -> datetime:
11+
return datetime.now(timezone.utc)
12+
13+
class ContactEntryModel(rx.Model, table=True):
14+
user_id: int | None = None
15+
first_name: str
16+
last_name: str | None = None
17+
email: str | None = None # = Field(nullable=True)
18+
message: str
19+
created_at: datetime = Field(
20+
default_factory=get_utc_now,
21+
sa_type=sqlalchemy.DateTime(timezone=True),
22+
sa_column_kwargs={
23+
'server_default': sqlalchemy.func.now()
24+
},
25+
nullable=False
26+
)

full_stack_python/contact/page.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import reflex as rx
2+
3+
from .. import navigation
4+
from ..ui.base import base_page
5+
6+
from . import form, state
7+
8+
def contact_page() -> rx.Component:
9+
my_child = rx.vstack(
10+
rx.heading("Contact Us", size="9"),
11+
rx.cond(state.ContactState.did_submit, state.ContactState.thank_you, ""),
12+
rx.desktop_only(
13+
rx.box(
14+
form.contact_form(),
15+
width='50vw'
16+
)
17+
),
18+
rx.tablet_only(
19+
rx.box(
20+
form.contact_form(),
21+
width='75vw'
22+
)
23+
),
24+
rx.mobile_only(
25+
rx.box(
26+
form.contact_form(),
27+
width='95vw'
28+
)
29+
),
30+
spacing="5",
31+
justify="center",
32+
align="center",
33+
min_height="85vh",
34+
id='my-child'
35+
)
36+
return base_page(my_child)

full_stack_python/contact/state.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import asyncio
2+
import reflex as rx
3+
4+
from .model import ContactEntryModel
5+
6+
class ContactState(rx.State):
7+
form_data: dict = {}
8+
did_submit: bool = False
9+
timeleft: int = 5
10+
11+
@rx.var
12+
def timeleft_label(self):
13+
if self.timeleft < 1:
14+
return "No time left"
15+
return f"{self.timeleft} seconds"
16+
17+
@rx.var
18+
def thank_you(self):
19+
first_name = self.form_data.get("first_name") or ""
20+
return f"Thank you {first_name}".strip() + "!"
21+
22+
async def handle_submit(self, form_data: dict):
23+
"""Handle the form submit."""
24+
# print(form_data)
25+
self.form_data = form_data
26+
data = {}
27+
for k,v in form_data.items():
28+
if v == "" or v is None:
29+
continue
30+
data[k] = v
31+
with rx.session() as session:
32+
db_entry = ContactEntryModel(
33+
**data
34+
)
35+
session.add(db_entry)
36+
session.commit()
37+
self.did_submit = True
38+
yield
39+
await asyncio.sleep(2)
40+
self.did_submit = False
41+
yield

full_stack_python/full_stack_python.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from rxconfig import config
66
from .ui.base import base_page
77

8-
from . import navigation, pages
8+
from . import navigation, pages, contact
99

1010
class State(rx.State):
1111
"""The app state."""
@@ -48,5 +48,7 @@ def index() -> rx.Component:
4848
app.add_page(index)
4949
app.add_page(pages.about_page,
5050
route=navigation.routes.ABOUT_US_ROUTE)
51+
app.add_page(contact.contact_page,
52+
route=navigation.routes.CONTACT_US_ROUTE)
5153
app.add_page(pages.pricing_page,
5254
route=navigation.routes.PRICING_ROUTE)
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from .about import about_page
22
from .pricing import pricing_page
3-
from .contact import contact_page
3+
# from .contact import contact_page
44

55
__all__ = [
66
'about_page',
7-
'contact_page',
7+
# 'contact_page',
88
'pricing_page'
99
]

full_stack_python/pages/contact.py

Lines changed: 0 additions & 140 deletions
This file was deleted.

0 commit comments

Comments
 (0)