Skip to content

Commit

Permalink
feat: redesign recording listing
Browse files Browse the repository at this point in the history
  • Loading branch information
lart2150 committed Nov 6, 2022
1 parent 7f06876 commit 97d56d1
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 96 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
npm-debug.log*
.eslintcache
/stats.html
/config.js
/config.json
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## Setup

- `npm install`
- `cp config.js.dist config.js`
- update config.js with base url for api and auth0 settings
- `cp config.json.dist config.json`
- update config.json with base url for api and auth0 settings
- `npm start`

File renamed without changes.
62 changes: 31 additions & 31 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"@emotion/styled": "^11.10.4",
"@fontsource/roboto": "^4.5.8",
"@mui/icons-material": "^5.10.9",
"@mui/material": "^5.10.9",
"@mui/material": "^5.10.12",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^6.2.2",
Expand Down
9 changes: 5 additions & 4 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { useAuth0 } from '@auth0/auth0-react';
import React from 'react';
import { lazy, Suspense, useEffect } from 'react';
import {BrowserRouter, Routes, Route} from 'react-router-dom';
import Layout from './Layout';
import Home from './pages/Home';

const Home = lazy(() => import('@/pages/Home'));

const App = () : JSX.Element => {
const { loginWithRedirect, isAuthenticated, isLoading} = useAuth0();
React.useEffect(() => {
useEffect(() => {
if (!isAuthenticated && !isLoading) {
loginWithRedirect();
}
Expand All @@ -20,7 +21,7 @@ const App = () : JSX.Element => {
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout/>}>
<Route index element={<Home/>}/>
<Route index element={<Suspense fallback={<div>loading...</div>}><Home/></Suspense>}/>
</Route>
</Routes>
</BrowserRouter>
Expand Down
2 changes: 1 addition & 1 deletion src/components/TivoContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const fetchValidator = z.object({
export const TivoContextComponent = ({children} : Props) => {
const [ctx, setCtx] = useState<TivoContextType|null>(null);
useEffect(() => {
fetch('config.js').then(rsp => {
fetch('config.json').then(rsp => {
rsp.json().then( data => {
console.log('data', data);
const validatedData = fetchValidator.parse(data)
Expand Down
136 changes: 82 additions & 54 deletions src/pages/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@ import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import ListItemButton from '@mui/material/ListItemButton';
import ListItemText from '@mui/material/ListItemText';
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
import Accordion from '@mui/material/Accordion';
import AccordionSummary from '@mui/material/AccordionSummary';
import AccordionDetails from '@mui/material/AccordionDetails';
import type { Channel, Recording } from '@/types/Tivo';
import { useFetch } from '@/util/api';
import { lazy, useEffect, useState, Suspense} from 'react';
import { Box, Tabs, Tab} from '@mui/material';
import { Box, Tabs, Tab, Chip} from '@mui/material';
import Container from '@mui/system/Container';

const Playback = lazy(() => import('@/components/Playback'));
const ChannelComponent = lazy(() => import('@/components/ChannelComponent'));
Expand Down Expand Up @@ -39,6 +45,7 @@ function TabPanel(props: TabPanelProps) {

const Home = () : JSX.Element => {
const [recordings, setRecordings] = useState<Recording[]>([]);
const [uniqueCollections, setUniqueCollections] = useState<Recording[]>([]);
const [channels, setChannels] = useState<Channel[]>([]);
const [selectedRecording, setSelectedRecording] = useState<Recording|null>(null);
const [selectedChannel, setSelectedChannel] = useState<Channel|null>(null);
Expand All @@ -53,7 +60,9 @@ const Home = () : JSX.Element => {

useEffect(() => {
fetch('/getMyShows').then(async (rec) => {
setRecordings(await rec.json());
const rawRecordings = await rec.json() as Recording[];
setUniqueCollections(rawRecordings.filter((r, i) => rawRecordings.findIndex(or => or.collectionId === r.collectionId) === i));
setRecordings(rawRecordings);
});
fetch('/getMyLineup').then(async (rec) => {
const allChannels = await rec.json();
Expand All @@ -63,67 +72,86 @@ const Home = () : JSX.Element => {
});
},[]);

useEffect(() => {
console.log('selectedRecording', selectedRecording);
}, [selectedRecording]);

console.log('uniqueCollections', uniqueCollections);
return (
<>
<Typography variant="h6">Home</Typography>
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<Tabs sx={{paddingX: 3}} value={tab} onChange={changeTab} aria-label="basic tabs example">
<Tab label="Recordings"/>
<Tab label="Channels"/>
</Tabs>
</Box>
<TabPanel value={tab} index={0}>
<List>
{recordings.map((recording) => {
const episode = recording.episodeNum?.length > 0 ? `S${recording.seasonNumber} E${recording.episodeNum.join(',')} ` : ``;
const secondary = `${episode}${recording.subtitle}`;
return <ListItem disablePadding key={recording.recordingId}>
<ListItemButton
onClick={() => {
console.log('recording', recording);
setSelectedRecording(recording);
}}
>
<ListItemText
primary={recording.collectionTitle}
secondary={secondary}
/>
</ListItemButton>
</ListItem>
})}
</List>
</TabPanel>
<TabPanel value={tab} index={1}>
<List>
{channels.map((channel) => {
return <ListItem disablePadding key={channel.stbChannelId}>
<ListItemButton
onClick={() => {
console.log('channel', channel);
setSelectedChannel(channel);
}}
<Container maxWidth="lg">
<Typography variant="h6">Home</Typography>
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<Tabs sx={{paddingX: 3}} value={tab} onChange={changeTab} aria-label="basic tabs example">
<Tab label="Recordings"/>
<Tab label="Channels"/>
</Tabs>
</Box>
<TabPanel value={tab} index={0}>

{uniqueCollections.map((c, i) => {
const collectionRecordings = recordings.filter(r => r.collectionId === c.collectionId).reverse();
const latestRecording = collectionRecordings.length ?
new Date(collectionRecordings[0].actualStartTime).toLocaleDateString() :
'';
return <Accordion key={c.collectionId}>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
>
<ListItemText
primary={channel.channelNumber + ' ' + channel.callSign}
secondary={channel.affiliate}
/>
</ListItemButton>
</ListItem>
})}
</List>
</TabPanel>
<Suspense fallback={<div>Loading...</div>}>
<Chip sx={{mr: 1}} label={collectionRecordings.length}/>
<Typography>{c.collectionTitle} {latestRecording}</Typography>
</AccordionSummary>
<AccordionDetails>
<List>
{collectionRecordings.map(recording => {
const recordingStart = new Date(recording.scheduledStartTime).toLocaleString();
const episode = recording.episodeNum?.length > 0 ? `S${recording.seasonNumber} E${recording.episodeNum.join(',')} ` : ``;
const secondary = `${episode}${recording.subtitle}`;
return <ListItem disablePadding key={recording.recordingId}>
<ListItemButton
onClick={() => {
console.log('recording', recording);
setSelectedRecording(recording);
}}
>
<ListItemText
primary={recordingStart}
secondary={secondary}
/>
</ListItemButton>
</ListItem>
})}
</List>
</AccordionDetails>
</Accordion>
})}
</TabPanel>
<TabPanel value={tab} index={1}>
<List>
{channels.map((channel) => {
return <ListItem disablePadding key={channel.stbChannelId}>
<ListItemButton
onClick={() => {
console.log('channel', channel);
setSelectedChannel(channel);
}}
>
<ListItemText
primary={channel.channelNumber + ' ' + channel.callSign}
secondary={channel.affiliate}
/>
</ListItemButton>
</ListItem>
})}
</List>
</TabPanel>
</Container>
<Suspense fallback={<div></div>}>
<Playback
openState={selectedRecording !== null}
close={() => {setSelectedRecording(null)}}
recording={selectedRecording}
/>
</Suspense>
<Suspense fallback={<div>Loading...</div>}>
<Suspense fallback={<div></div>}>
<ChannelComponent
openState={selectedChannel !== null}
close={() => {setSelectedChannel(null)}}
Expand Down
Loading

0 comments on commit 97d56d1

Please sign in to comment.