File size: 6,152 Bytes
13fc29d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
"""
Streamlit app: SolarWine — Smart Shading for Vineyard Solar Panels.
5 tabs: Overview, Photosynthesis & Data, Forecasting, Shading Simulator, Documentation.
"""

from __future__ import annotations

import sys
from pathlib import Path

PROJECT_ROOT = Path(__file__).resolve().parent
if str(PROJECT_ROOT) not in sys.path:
    sys.path.insert(0, str(PROJECT_ROOT))

try:
    from dotenv import load_dotenv
    load_dotenv(PROJECT_ROOT / ".env")
except ImportError:
    pass

import os
import streamlit as st

# Copy Streamlit secrets into os.environ so downstream clients (ThingsBoard,
# IMS, etc.) can read them via os.environ without any code changes.
for key, value in st.secrets.items():
    if isinstance(value, str) and key not in os.environ:
        os.environ[key] = value

from ui.bootstrap import img_to_base64, now_israel

# ---------------------------------------------------------------------------
# Page config
# ---------------------------------------------------------------------------

st.set_page_config(page_title="SolarWine - Smart Shading for Vineyards", layout="wide")

# ---------------------------------------------------------------------------
# Migration banner (shows only when new frontend URL is configured)
# ---------------------------------------------------------------------------
_NEW_FRONTEND_URL = os.environ.get("SOLARWINE_FRONTEND_URL", "")
if _NEW_FRONTEND_URL:
    st.info(
        f"A new version of the SolarWine dashboard is available at "
        f"[{_NEW_FRONTEND_URL}]({_NEW_FRONTEND_URL}). "
        f"This Streamlit app will be retired soon.",
        icon="🔄",
    )

# ---------------------------------------------------------------------------
# Brand CSS
# ---------------------------------------------------------------------------

_BRAND_GREEN = "#00BD3E"
_BRAND_DARK = "#1A1A1A"

st.markdown(f"""
<style>
    /* SolarWine brand overrides — async font load (non-blocking) */
    @font-face {{
        font-family: 'Open Sans';
        font-style: normal;
        font-weight: 300 400 600 700;
        font-display: swap;
        src: url('https://fonts.gstatic.com/s/opensans/v40/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS-mu0SC55I.woff2') format('woff2');
    }}

    html, body, [class*="css"] {{
        font-family: 'Open Sans', sans-serif;
    }}

    /* Header bar */
    header[data-testid="stHeader"] {{
        background-color: {_BRAND_DARK};
    }}

    /* Metric value color */
    [data-testid="stMetricValue"] {{
        color: {_BRAND_GREEN};
    }}

    /* Tab labels */
    button[data-baseweb="tab"] {{
        font-weight: 600;
    }}

    /* Sidebar background */
    section[data-testid="stSidebar"] {{
        background-color: {_BRAND_DARK};
    }}
    section[data-testid="stSidebar"] * {{
        color: #FFFFFF !important;
    }}
    section[data-testid="stSidebar"] button {{
        background-color: {_BRAND_GREEN} !important;
        color: #FFFFFF !important;
        border: none !important;
        border-radius: 6px !important;
    }}
    section[data-testid="stSidebar"] button:hover {{
        background-color: #00a035 !important;
    }}

    /* Hero banner */
    .hero-banner {{
        background: linear-gradient(135deg, {_BRAND_DARK} 0%, #2d3a2d 100%);
        padding: 2rem 2.5rem;
        border-radius: 12px;
        margin-bottom: 1.5rem;
        display: flex;
        align-items: center;
        gap: 2rem;
    }}
    .hero-banner img {{
        max-height: 48px;
    }}
    .hero-text {{
        color: #FFFFFF;
    }}
    .hero-text h1 {{
        margin: 0 0 0.3rem 0;
        font-size: 1.8rem;
        font-weight: 700;
        color: #FFFFFF;
    }}
    .hero-text p {{
        margin: 0;
        font-size: 1.05rem;
        color: #B8D4B8;
    }}
</style>
""", unsafe_allow_html=True)

# ---------------------------------------------------------------------------
# Hero banner with logo
# ---------------------------------------------------------------------------

_ASSETS = PROJECT_ROOT / "assets"
_logo_path = _ASSETS / "logo.png"

if _logo_path.exists():
    _logo_b64 = img_to_base64(_logo_path)
    st.markdown(f"""
    <div class="hero-banner">
        <img src="data:image/png;base64,{_logo_b64}" alt="SolarWine logo">
        <div class="hero-text">
            <h1>Smart Shading for Vineyard Solar Panels</h1>
            <p>Empowering growers · Harvesting sunshine</p>
        </div>
    </div>
    """, unsafe_allow_html=True)
else:
    st.title("SolarWine — Smart Shading for Vineyard Solar Panels")

# ---------------------------------------------------------------------------
# Sidebar
# ---------------------------------------------------------------------------

sidebar = st.sidebar
if _logo_path.exists():
    sidebar.image(str(_logo_path), width=180)

_now = now_israel()
sidebar.caption("**Site:** Yeruham, Israel")
sidebar.markdown(f"**Date:** {_now.strftime('%Y-%m-%d')}")
sidebar.markdown(f"**Time (local):** {_now.strftime('%H:%M')}")
st.session_state.current_time_israel = _now

# ---------------------------------------------------------------------------
# Navigation — only the selected page renders (avoids running all 6 tabs)
# ---------------------------------------------------------------------------

_PAGES = [
    "System Status",
    "Overview",
    "Photosynthesis & Data",
    "Forecasting",
    "Shading Simulator",
    "Documentation",
]

_selected = sidebar.radio("Navigate", _PAGES, label_visibility="collapsed")

if _selected == "System Status":
    from ui.tab_system_status import render_tab_system_status
    render_tab_system_status()
elif _selected == "Overview":
    from ui.tab_overview import render_tab_overview
    render_tab_overview()
elif _selected == "Photosynthesis & Data":
    from ui.tab_data import render_tab_data
    render_tab_data()
elif _selected == "Forecasting":
    from ui.tab_forecast import render_tab_forecast
    render_tab_forecast()
elif _selected == "Shading Simulator":
    from ui.tab_shading import render_tab_shading
    render_tab_shading()
elif _selected == "Documentation":
    from ui.tab_docs import render_tab_docs
    render_tab_docs()