Skip to content

Commit a81bb6c

Browse files
committed
company dashboard from flexgen
1 parent a74e268 commit a81bb6c

File tree

16 files changed

+748
-2
lines changed

16 files changed

+748
-2
lines changed

.github/workflows/deploy.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ jobs:
3535
ai_image_gen)
3636
echo "EXTRA_ARGS=--env REPLICATE_API_TOKEN=${{ secrets.REPLICATE_API_TOKEN }}" >> $GITHUB_ENV
3737
;;
38+
company_dashboard)
39+
echo "EXTRA_ARGS=" >> $GITHUB_ENV
40+
;;
3841
customer_data_app)
3942
cat .deploy/temporary_db.py >> ${{ matrix.folder }}/customer_data/customer_data.py
4043
echo "EXTRA_ARGS=--vmtype ${{ vars.CUSTOMER_DATA_VM_TYPE }}" >> $GITHUB_ENV
4.19 KB
Binary file not shown.

company_dashboard/company_dashboard/__init__.py

Whitespace-only changes.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import reflex as rx
2+
from company_dashboard.components.sidebar import sidebar
3+
from company_dashboard.components.header import header_bar
4+
from company_dashboard.components.key_metrics import key_metrics_section
5+
from company_dashboard.components.visitors_chart import (
6+
visitors_chart_section,
7+
)
8+
from company_dashboard.components.documents_table import (
9+
documents_table_section,
10+
)
11+
from company_dashboard.states.dashboard_state import DashboardState
12+
13+
14+
def index() -> rx.Component:
15+
"""The main dashboard page."""
16+
return rx.el.div(
17+
sidebar(),
18+
rx.el.main(
19+
header_bar(),
20+
rx.el.div(
21+
key_metrics_section(),
22+
visitors_chart_section(),
23+
documents_table_section(),
24+
class_name="p-6 space-y-6",
25+
),
26+
class_name="ml-64 w-full h-[100vh] overflow-y-auto",
27+
),
28+
class_name="flex bg-gray-50 h-[100vh] w-full overflow-hidden",
29+
on_mount=DashboardState.load_initial_data,
30+
)
31+
32+
33+
app = rx.App(
34+
theme=rx.theme(appearance="light"),
35+
stylesheets=["https://cdn.tailwindcss.com"],
36+
style={
37+
rx.el.label: {"font_family": "JetBrains Mono,ui-monospace,monospace"},
38+
rx.el.span: {"font_family": "JetBrains Mono,ui-monospace,monospace"},
39+
rx.el.h1: {"font_family": "JetBrains Mono,ui-monospace,monospace"},
40+
rx.el.h2: {"font_family": "JetBrains Mono,ui-monospace,monospace"},
41+
},
42+
)
43+
app.add_page(index, route="/")

company_dashboard/company_dashboard/components/__init__.py

Whitespace-only changes.
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
import reflex as rx
2+
from company_dashboard.states.dashboard_state import (
3+
DashboardState,
4+
DocumentRow,
5+
)
6+
7+
8+
def document_tab_button(text: str, count: int = 0) -> rx.Component:
9+
"""Button for selecting document table tabs."""
10+
return rx.el.button(
11+
text,
12+
rx.cond(
13+
count > 0,
14+
rx.el.span(
15+
count,
16+
class_name="ml-1.5 px-1.5 py-0.5 text-xs font-medium rounded-full bg-gray-200 text-gray-600",
17+
),
18+
rx.fragment(),
19+
),
20+
on_click=lambda: DashboardState.set_document_tab(text),
21+
class_name=rx.cond(
22+
DashboardState.selected_document_tab == text,
23+
"px-3 py-1.5 text-sm font-medium text-gray-700 bg-gray-100 border border-gray-300 rounded-md shadow-sm",
24+
"px-3 py-1.5 text-sm font-medium text-gray-500 bg-white border border-transparent rounded-md hover:bg-gray-50 hover:text-gray-700",
25+
),
26+
)
27+
28+
29+
def status_badge(status: rx.Var[str]) -> rx.Component:
30+
"""Displays a status badge based on the status string."""
31+
return rx.el.span(
32+
rx.icon(
33+
tag=rx.match(
34+
status,
35+
("Done", "check-circle"),
36+
("In Process", "loader"),
37+
("Pending", "alert-circle"),
38+
"help-circle",
39+
),
40+
# size=10,
41+
class_name="mr-1.5 size-4",
42+
),
43+
status,
44+
class_name=rx.match(
45+
status,
46+
(
47+
"Done",
48+
"inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800",
49+
),
50+
(
51+
"In Process",
52+
"inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800",
53+
),
54+
(
55+
"Pending",
56+
"inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800",
57+
),
58+
"inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800",
59+
),
60+
)
61+
62+
63+
def documents_table_section() -> rx.Component:
64+
"""The section displaying the documents table."""
65+
return rx.el.div(
66+
rx.el.div(
67+
rx.el.div(
68+
document_tab_button("Outline"),
69+
document_tab_button("Past Performance", 3),
70+
document_tab_button("Key Personnel", 2),
71+
document_tab_button("Focus Documents"),
72+
class_name="flex items-center space-x-2 border-b border-gray-200 pb-2 mb-4",
73+
),
74+
rx.el.div(
75+
rx.el.button(
76+
rx.icon(
77+
tag="list-filter",
78+
class_name="w-4 h-4 mr-2",
79+
),
80+
"Customize Columns",
81+
rx.icon(
82+
tag="chevron-down",
83+
class_name="w-4 h-4 ml-1",
84+
),
85+
class_name="flex items-center px-3 py-1.5 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md shadow-sm hover:bg-gray-50",
86+
),
87+
rx.el.button(
88+
rx.icon(
89+
tag="plus",
90+
class_name="w-4 h-4 mr-2",
91+
),
92+
"Add Section",
93+
class_name="flex items-center px-3 py-1.5 text-sm font-medium text-white bg-gray-800 border border-transparent rounded-md shadow-sm hover:bg-gray-700",
94+
),
95+
class_name="flex items-center space-x-3",
96+
),
97+
class_name="flex items-center justify-between mb-4",
98+
),
99+
rx.el.div(
100+
rx.el.table(
101+
rx.el.thead(
102+
rx.el.tr(
103+
rx.foreach(
104+
DashboardState.document_columns,
105+
lambda col_name: rx.el.th(
106+
col_name,
107+
scope="col",
108+
class_name="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider",
109+
),
110+
)
111+
),
112+
class_name="bg-gray-50",
113+
),
114+
rx.el.tbody(
115+
rx.foreach(
116+
DashboardState.document_data,
117+
lambda row: rx.el.tr(
118+
rx.el.td(
119+
rx.el.div(
120+
rx.icon(
121+
tag="grip-vertical",
122+
class_name="w-4 h-4 text-gray-400 mr-3 cursor-grab",
123+
),
124+
rx.el.input(
125+
type="checkbox",
126+
class_name="h-4 w-4 text-indigo-600 border-gray-300 rounded focus:ring-indigo-500",
127+
),
128+
class_name="flex items-center",
129+
),
130+
class_name="px-4 py-3 whitespace-nowrap",
131+
),
132+
rx.el.td(
133+
row["header"],
134+
class_name="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900",
135+
),
136+
rx.el.td(
137+
row["section_type"],
138+
class_name="px-4 py-3 whitespace-nowrap text-sm text-gray-500",
139+
),
140+
rx.el.td(
141+
status_badge(row["status"]),
142+
class_name="px-4 py-3 whitespace-nowrap text-sm text-gray-500",
143+
),
144+
rx.el.td(
145+
row["target"],
146+
class_name="px-4 py-3 whitespace-nowrap text-sm text-gray-500",
147+
),
148+
rx.el.td(
149+
row["limit"],
150+
class_name="px-4 py-3 whitespace-nowrap text-sm text-gray-500",
151+
),
152+
rx.el.td(
153+
row["reviewer"],
154+
class_name="px-4 py-3 whitespace-nowrap text-sm text-gray-500",
155+
),
156+
),
157+
),
158+
class_name="bg-white divide-y divide-gray-200",
159+
),
160+
class_name="min-w-full divide-y divide-gray-200",
161+
),
162+
class_name="overflow-hidden border border-gray-200 rounded-lg shadow-sm",
163+
),
164+
class_name="p-5 bg-white border border-gray-200 rounded-lg shadow-sm mt-5",
165+
)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import reflex as rx
2+
3+
4+
def header_bar() -> rx.Component:
5+
"""The header bar component."""
6+
return rx.el.div(
7+
rx.el.div(
8+
rx.el.label(
9+
"reflex › build › ",
10+
class_name="text-sm font-semibold text-gray-500",
11+
),
12+
rx.el.label(
13+
"dashboard",
14+
class_name="text-sm font-semibold text-gray-900",
15+
),
16+
),
17+
rx.el.div(),
18+
class_name="flex items-center justify-between h-12 px-6 bg-white border-b border-gray-200",
19+
)
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import reflex as rx
2+
from company_dashboard.states.dashboard_state import (
3+
DashboardState,
4+
Metric,
5+
)
6+
7+
8+
def metric_card(metric: Metric) -> rx.Component:
9+
"""A card displaying a single key metric."""
10+
return rx.el.div(
11+
rx.el.div(
12+
rx.el.p(
13+
metric["title"],
14+
class_name="text-sm font-medium text-gray-500",
15+
),
16+
rx.el.div(
17+
rx.el.span(
18+
metric["change"],
19+
class_name=rx.cond(
20+
metric["change_direction"] == "up",
21+
"text-xs font-medium px-2 py-0.5 rounded-full bg-green-100 text-green-800",
22+
rx.cond(
23+
metric["change_direction"] == "down",
24+
"text-xs font-medium px-2 py-0.5 rounded-full bg-red-100 text-red-800",
25+
"text-xs font-medium px-2 py-0.5 rounded-full bg-gray-100 text-gray-800",
26+
),
27+
),
28+
),
29+
rx.icon(
30+
tag=rx.cond(
31+
metric["change_direction"] == "up",
32+
"trending-up",
33+
rx.cond(
34+
metric["change_direction"] == "down",
35+
"trending-down",
36+
"minus",
37+
),
38+
),
39+
size=16,
40+
class_name=rx.cond(
41+
metric["change_direction"] == "up",
42+
"text-green-600 ml-1",
43+
rx.cond(
44+
metric["change_direction"] == "down",
45+
"text-red-600 ml-1",
46+
"text-gray-600 ml-1",
47+
),
48+
),
49+
),
50+
class_name="flex items-center",
51+
),
52+
class_name="flex items-center justify-between mb-1",
53+
),
54+
rx.el.p(
55+
metric["value"],
56+
class_name="text-3xl font-semibold text-gray-900 mb-2",
57+
),
58+
rx.el.div(
59+
rx.el.p(
60+
metric["description"],
61+
class_name="text-sm text-gray-700 mr-1",
62+
),
63+
rx.icon(
64+
tag="bar-chart-2",
65+
size=16,
66+
class_name="text-gray-500",
67+
),
68+
class_name="flex items-center text-sm text-gray-500",
69+
),
70+
rx.el.p(
71+
metric["trend_description"],
72+
class_name="text-xs text-gray-400 mt-1",
73+
),
74+
class_name="p-5 bg-white border border-gray-200 rounded-lg shadow-sm",
75+
)
76+
77+
78+
def key_metrics_section() -> rx.Component:
79+
"""The section displaying key metric cards."""
80+
return rx.el.div(
81+
rx.foreach(DashboardState.key_metrics, metric_card),
82+
class_name="grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-4",
83+
)
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import reflex as rx
2+
3+
4+
def sidebar_item(
5+
text: str,
6+
icon: str,
7+
href: str = "#",
8+
is_active: bool = False,
9+
) -> rx.Component:
10+
"""A reusable sidebar item component."""
11+
return rx.el.a(
12+
rx.icon(tag=icon, class_name="mr-3 size-4"),
13+
rx.el.label(text, class_name="text-sm"),
14+
href=href,
15+
class_name=rx.cond(
16+
is_active,
17+
"flex items-center px-4 py-2 text-sm font-medium text-gray-900 bg-gray-100 rounded-lg",
18+
"flex items-center px-4 py-2 text-sm font-medium text-gray-600 hover:bg-gray-50 hover:text-gray-900 rounded-lg",
19+
),
20+
)
21+
22+
23+
def sidebar() -> rx.Component:
24+
"""The sidebar component for the dashboard."""
25+
return rx.el.div(
26+
rx.el.div(
27+
rx.el.div(
28+
rx.el.label(
29+
"Reflex Build",
30+
class_name="text-sm font-semibold text-gray-900",
31+
),
32+
rx.el.label(
33+
"v.0.0.1",
34+
class_name="text-sm font-regular text-gray-500",
35+
),
36+
class_name="flex items-center px-2 h-12 justify-between",
37+
),
38+
rx.el.label(
39+
"Projects",
40+
class_name="px-4 mb-2 text-sm font-semibold tracking-wider text-gray-500 uppercase",
41+
),
42+
rx.el.nav(
43+
sidebar_item(
44+
"Dashboard",
45+
"layout-dashboard",
46+
is_active=True,
47+
),
48+
sidebar_item("Lifecycle", "recycle"),
49+
sidebar_item("Analytics", "bar-chart-3"),
50+
sidebar_item("Projects", "folder"),
51+
sidebar_item("Team", "users"),
52+
class_name="space-y-1 mb-6 pt-2",
53+
),
54+
rx.el.label(
55+
"Documents",
56+
class_name="px-4 mb-2 text-sm font-semibold tracking-wider text-gray-500 uppercase",
57+
),
58+
rx.el.nav(
59+
sidebar_item("Data Library", "database"),
60+
sidebar_item("Reports", "file-text"),
61+
sidebar_item("Word Assistant", "file-input"),
62+
sidebar_item("More", "send_horizontal"),
63+
class_name="space-y-1",
64+
),
65+
),
66+
class_name="flex flex-col justify-between w-64 h-screen px-2 bg-white border-r border-gray-200 fixed",
67+
)

0 commit comments

Comments
 (0)