@@ -27,6 +27,8 @@ import VideocamOutlined from '@mui/icons-material/VideocamOutlined';
2727import { BirdIcon } from '../../components/icons/BirdIcon' ;
2828import { PageHelp } from '../../components/PageHelp' ;
2929import { overviewHelpConfig } from '../../page-help-config' ;
30+ import { useProtectedArea } from '../../contexts/ProtectedAreaContext' ;
31+ import Tooltip from '@mui/material/Tooltip' ;
3032
3133const formatHour = ( hour : number ) => {
3234 const date = new Date ( ) ;
@@ -36,6 +38,7 @@ const formatHour = (hour: number) => {
3638
3739export const Overview = ( ) => {
3840 const { t } = useTranslation ( ) ;
41+ const { canEdit } = useProtectedArea ( ) ;
3942 const [ selectedDay , setSelectedDay ] = useState < Dayjs > ( dayjs ( ) ) ;
4043 const [ downloadingPdf , setDownloadingPdf ] = useState ( false ) ;
4144
@@ -114,24 +117,29 @@ export const Overview = () => {
114117 format = "YYYY-MM-DD"
115118 />
116119 </ LocalizationProvider >
117- < Button
118- variant = "outlined"
119- size = "medium"
120- startIcon = { < DownloadIcon /> }
121- disabled = { downloadingPdf }
122- onClick = { async ( ) => {
123- setDownloadingPdf ( true ) ;
124- try {
125- await downloadReportPdf ( selectedDay . format ( 'YYYY-MM' ) ) ;
126- } catch ( err ) {
127- console . error ( 'PDF download failed:' , err ) ;
128- } finally {
129- setDownloadingPdf ( false ) ;
130- }
131- } }
132- >
133- { downloadingPdf ? '...' : t ( 'overview.downloadPdf' ) }
134- </ Button >
120+ < Tooltip title = { ! canEdit ? t ( 'common.loginRequiredForExport' ) : undefined } >
121+ < span >
122+ < Button
123+ variant = "outlined"
124+ size = "medium"
125+ startIcon = { < DownloadIcon /> }
126+ disabled = { downloadingPdf || ! canEdit }
127+ onClick = { async ( ) => {
128+ if ( ! canEdit ) return ;
129+ setDownloadingPdf ( true ) ;
130+ try {
131+ await downloadReportPdf ( selectedDay . format ( 'YYYY-MM' ) ) ;
132+ } catch ( err ) {
133+ console . error ( 'PDF download failed:' , err ) ;
134+ } finally {
135+ setDownloadingPdf ( false ) ;
136+ }
137+ } }
138+ >
139+ { downloadingPdf ? '...' : t ( 'overview.downloadPdf' ) }
140+ </ Button >
141+ </ span >
142+ </ Tooltip >
135143 </ Box >
136144 </ Grid >
137145 </ Grid >
@@ -254,25 +262,33 @@ export const Overview = () => {
254262 { weather && < WeatherCard weather = { weather } /> }
255263 </ Grid >
256264
257- { /* Feed Control */ }
258- < Grid size = { { xs : 12 , sm : 6 , md : 4 } } sx = { { display : 'flex' } } >
259- < FeedCard />
260- </ Grid >
261-
262- { /* Hourly Activity Line Chart */ }
263- < Grid size = { { xs : 12 , md : 8 } } sx = { { display : 'flex' } } >
264- < Paper sx = { { p : 2 , width : '100%' } } >
265- < Typography variant = "h6" gutterBottom >
266- { t ( 'overview.hourlyActivity' ) }
267- </ Typography >
268- { overviewData ?. topSpecies && overviewData . topSpecies . length > 0 ? (
269- < HourlyActivityChart data = { overviewData . topSpecies } />
270- ) : (
271- < Typography color = "text.secondary" sx = { { py : 4 } } >
272- { t ( 'overview.noData' ) }
265+ { /* Feed Control + Hourly Activity — в одной строке без зазора */ }
266+ < Grid size = { 12 } >
267+ < Box
268+ sx = { {
269+ display : 'grid' ,
270+ gridTemplateColumns : { xs : '1fr' , sm : 'minmax(280px, 320px) 1fr' } ,
271+ gap : 2 ,
272+ alignItems : 'stretch' ,
273+ width : '100%' ,
274+ } }
275+ >
276+ < Box >
277+ < FeedCard />
278+ </ Box >
279+ < Paper sx = { { p : 2 , minWidth : 0 } } >
280+ < Typography variant = "h6" gutterBottom >
281+ { t ( 'overview.hourlyActivity' ) }
273282 </ Typography >
274- ) }
275- </ Paper >
283+ { overviewData ?. topSpecies && overviewData . topSpecies . length > 0 ? (
284+ < HourlyActivityChart data = { overviewData . topSpecies } />
285+ ) : (
286+ < Typography color = "text.secondary" sx = { { py : 4 } } >
287+ { t ( 'overview.noData' ) }
288+ </ Typography >
289+ ) }
290+ </ Paper >
291+ </ Box >
276292 </ Grid >
277293 </ Grid >
278294
0 commit comments