diff --git a/src/config/configs.ts b/src/config/configs.ts index 05b928da574ee365b225b446f266146ae0570d8d..e53b23086c10c7c76703b4535e7e8546c88081df 100644 --- a/src/config/configs.ts +++ b/src/config/configs.ts @@ -7,4 +7,11 @@ export const authHeader = { Authorization: `Bearer ${CookieManager.readCookie('token')}`, 'Content-Type': 'application/json', }, -}; \ No newline at end of file +}; + +export function sessionInvalid(){ + alert('session invalid, please login again!'); + localStorage.clear(); + CookieManager.deleteCookie('token'); + window.location.href = '/'; +} \ No newline at end of file diff --git a/src/pages/Main/Main.tsx b/src/pages/Main/Main.tsx index a46b74aa04729451c9edc959179f9e6bbc8f938f..f30b4c8b425aa34262c9e5b0be27d328b3ea1bfa 100644 --- a/src/pages/Main/Main.tsx +++ b/src/pages/Main/Main.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react'; import { Box, Button, Center, Flex, Grid, GridItem, Heading, Image } from '@chakra-ui/react'; import axios from 'axios'; import Navbar from '../../components/Navbar/Navbar'; -import { restUrl, authHeader } from '../../config/configs'; +import { restUrl, authHeader, sessionInvalid } from '../../config/configs'; const Main: React.FC = () => { const [forYou, setForYou] = useState<any[]>([]); @@ -22,13 +22,12 @@ const Main: React.FC = () => { console.error('Error fetching data:', error); if(error.response.status === 401){ - alert('authentication failed! token is deprecated!'); + sessionInvalid(); + } else if(error.response.status === 403){ - alert('authentication failed! invalid token!'); - } - // localStorage.clear(); - // window.location.href = '/'; + alert('forbidden!'); + } } }; diff --git a/src/pages/Referral/Referral.tsx b/src/pages/Referral/Referral.tsx index b9fa6ecb5739af3593f4e5f66b6a9bc63c7d37ff..9012811b4fca07d768cf871915aa946882d4b028 100644 --- a/src/pages/Referral/Referral.tsx +++ b/src/pages/Referral/Referral.tsx @@ -1,194 +1,178 @@ -import React, {useEffect} from 'react'; -import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; -import { Box, Button, Center, Flex, Grid, GridItem, Heading, Image, Text, chakra, color, FormControl, Input } from '@chakra-ui/react' -import {IoMdAddCircleOutline} from "react-icons/io"; -import Navbar from "../../components/Navbar/Navbar"; +import React, { useEffect, useState } from 'react'; +import { Box, Button, Center, Flex, Grid, GridItem, Heading, Image, Text, chakra, FormControl, Input } from '@chakra-ui/react'; +import { IoMdAddCircleOutline } from 'react-icons/io'; +import { restUrl, authHeader, sessionInvalid} from '../../config/configs'; +import Navbar from '../../components/Navbar/Navbar'; +import axios from 'axios'; +import _ from 'lodash'; +import CookieManager from '../../auth/cookie'; -class Referral extends React.Component { - constructor(props : any){ - super(props); - } +const Referral: React.FC<any> = () => { + const [searchRenderer, setSearchRenderer] = useState<React.ReactNode[]>([]); + const [recommendRenderer, setRecommendRenderer] = useState<React.ReactNode[]>([]); - render(): React.ReactNode { - return ( - <> - <Navbar search =''/> - <Center> - <Flex width='100%' alignItems='center' flexDir='column'> - <Heading color='white' p='20px'>Choose Your Premium Song</Heading> + const [search, setSearch] = useState<string>(''); - <Text color='white' fontSize={{base:'2xl', lg:'4xl'}}> Recomendations:</Text> - <Box overflowY='scroll' maxH='300px' - maxW={{base : '80%', lg:'100%'}} - width='60%'> - - <Flex px={2} py={2} width="100%" height="fit-content" color="white" bgColor="black" justifyContent="space-between"> - <Flex> - <Image src="./logo_spotyphie.png" maxHeight={{ base: "40px", lg: "60px" }} /> - <chakra.div> - Title: title<br /> - Author: author - </chakra.div> - </Flex> - <chakra.div height="100%" paddingRight={2} paddingTop={2}> - <chakra.div fontSize="4xl" height='100%' > - <IoMdAddCircleOutline color="white" /> - </chakra.div> - </chakra.div> - </Flex> - <Flex px={2} py={2} width="100%" height="fit-content" color="white" bgColor="black" justifyContent="space-between"> - <Flex> - <Image src="./logo_spotyphie.png" maxHeight={{ base: "40px", lg: "60px" }} /> - <chakra.div> - Title: title<br /> - Author: author - </chakra.div> - </Flex> - <chakra.div height="100%" paddingRight={2} paddingTop={2}> - <chakra.div fontSize="4xl" height='100%' > - <IoMdAddCircleOutline color="white" /> - </chakra.div> - </chakra.div> - </Flex> - <Flex px={2} py={2} width="100%" height="fit-content" color="white" bgColor="black" justifyContent="space-between"> - <Flex> - <Image src="./logo_spotyphie.png" maxHeight={{ base: "40px", lg: "60px" }} /> - <chakra.div> - Title: title<br /> - Author: author - </chakra.div> - </Flex> - <chakra.div height="100%" paddingRight={2} paddingTop={2}> - <chakra.div fontSize="4xl" height='100%' > - <IoMdAddCircleOutline color="white" /> - </chakra.div> - </chakra.div> - </Flex> - <Flex px={2} py={2} width="100%" height="fit-content" color="white" bgColor="black" justifyContent="space-between"> + const debouncedSearch = _.debounce((event: React.ChangeEvent<HTMLInputElement>) => { + event.preventDefault(); + setSearch(event.target.value); + }, 700); + + + + function handleClickSong(id: number, title: string){ + try { + const confirmed = window.confirm(`Do you sure want to choose this song (${title})?`); + if (!confirmed) { + return; + } + let res = axios.post(`${restUrl}/referralPage/addSong`, { song_id: id }, authHeader); + alert('premium song succesfuly added to your song list!'); + localStorage.removeItem('referral'); + window.location.href = `/songPage?title=${title}`; + } catch (error) { + alert('bad session'); + console.error(error); + } + } + + const renderRecomendation = (rec: any[]): React.ReactNode[] => { + return rec.map((item, index) => ( + <Flex + px={2} + py={2} + width="100%" + height="fit-content" + color="white" + bgColor="black" + justifyContent="space-between" + > <Flex> - <Image src="./logo_spotyphie.png" maxHeight={{ base: "40px", lg: "60px" }} /> + <Image src={item.picture} maxHeight={{ base: '40px', lg: '60px' }} /> <chakra.div> - Title: title<br /> - Author: author + Title : {item.title} + <br /> + Artist : {item.artist} </chakra.div> </Flex> <chakra.div height="100%" paddingRight={2} paddingTop={2}> - <chakra.div fontSize="4xl" height='100%' > + <chakra.div fontSize="4xl" height="100%" onClick={() => handleClickSong(item.song_id, item.title)}> <IoMdAddCircleOutline color="white" /> </chakra.div> - </chakra.div> + </chakra.div> </Flex> + )); + }; + + const renderSearch = (sc: any[]): React.ReactNode[] => { + return sc.map((item, index) => ( + <GridItem w="100%" p={6}> + <Button + px={2} + py={2} + height="fit-content" + w="100%" + maxH={{ base: '50px', lg: '150px' }} + bgColor="#334F5B" + color="white" + onClick={() => handleClickSong(item.song_id, item.title)} + > + <Image + src="./logo_spotyphie.png" + maxHeight={{ base: '20px', lg: '60px' }} + justifySelf="left" + /> + Title : {item.title} + <br /> + Artist : {item.artist} + </Button> + </GridItem> + )); + }; + + + useEffect(() => { + const init = async () => { + + try{ + const params = new URLSearchParams(window.location.search); + const paramsObj = Object.fromEntries(params.entries()); + console.log(paramsObj.title); + const res = await axios.get(`${restUrl}/referralPage?title=${paramsObj.title}`, authHeader); + if(localStorage.getItem('referral') !== 'true'){ + alert('ups, kamu belum meredeem referral code!'); + window.location.href = '/'; + return; + } + setRecommendRenderer(renderRecomendation(res.data.recomendations)); + setSearchRenderer(renderSearch(res.data.search)); + } + catch(e : any){ + console.log(e); + if(e.response.status === 401){ + sessionInvalid() + } + } + + }; + + init(); + }, []); + + + + return ( + <> + <Navbar search="" /> + <Center> + <Flex width="100%" alignItems="center" flexDir="column"> + <Heading color="white" p="20px"> + Choose Your Premium Song + </Heading> + + <Text color="white" fontSize={{ base: '2xl', lg: '4xl' }}> + {' '} + Our Recomendations: + </Text> + <Box + overflowY="scroll" + maxH="300px" + maxW={{ base: '80%', lg: '100%' }} + width="60%" + > + {recommendRenderer} </Box> - <Heading color='white' p='20px'>Or search for the song...</Heading> - <Flex - > + <Heading color="white" p="20px"> + Or search for the song... + </Heading> + <Flex> <form> <FormControl> - <Input type='text' w='100%' variant='filled' color='white' placeholder="search..." height='90%'></Input> + <Input + type="text" + w="100%" + variant="filled" + color="white" + placeholder="search..." + height="90%" + onChange={debouncedSearch} + ></Input> </FormControl> </form> - </Flex> - <Grid templateColumns={{ base : 'repeat(1, 2fr)', lg : 'repeat(3,2fr)'}} columnGap={6} w='80%'> - <GridItem w='100%' p={6}> - <Button px={2} py={2} height='fit-content' w='100%' maxH={{base : '50px', lg:'150px'}} bgColor='#334F5B' color='white'> - <Image src="./logo_spotyphie.png" - maxHeight={{ base: "20px", lg: "60px" }} - justifySelf='left' - /> - Title : title<br/> - Author : author - </Button> - </GridItem> - <GridItem w='100%' p={6}> - <Button px={2} py={2} height='fit-content' w='100%' maxH={{base : '50px', lg:'150px'}} bgColor='#334F5B' color='white'> - <Image src="./logo_spotyphie.png" - maxHeight={{ base: "20px", lg: "60px" }} - justifySelf='left' - /> - Title : title<br/> - Author : author - </Button> - </GridItem> - <GridItem w='100%' p={6}> - <Button px={2} py={2} height='fit-content' w='100%' maxH={{base : '50px', lg:'150px'}} bgColor='#334F5B' color='white'> - <Image src="./logo_spotyphie.png" - maxHeight={{ base: "20px", lg: "60px" }} - justifySelf='left' - /> - Title : title<br/> - Author : author - </Button> - </GridItem> - <GridItem w='100%' p={6}> - <Button px={2} py={2} height='fit-content' w='100%' maxH={{base : '50px', lg:'150px'}} bgColor='#334F5B' color='white'> - <Image src="./logo_spotyphie.png" - maxHeight={{ base: "20px", lg: "60px" }} - justifySelf='left' - /> - Title : title<br/> - Author : author - </Button> - </GridItem> - <GridItem w='100%' p={6}> - <Button px={2} py={2} height='fit-content' w='100%' maxH={{base : '50px', lg:'150px'}} bgColor='#334F5B' color='white'> - <Image src="./logo_spotyphie.png" - maxHeight={{ base: "20px", lg: "60px" }} - justifySelf='left' - /> - Title : title<br/> - Author : author - </Button> - </GridItem> - <GridItem w='100%' p={6}> - <Button px={2} py={2} height='fit-content' w='100%' maxH={{base : '50px', lg:'150px'}} bgColor='#334F5B' color='white'> - <Image src="./logo_spotyphie.png" - maxHeight={{ base: "20px", lg: "60px" }} - justifySelf='left' - /> - Title : title<br/> - Author : author - </Button> - </GridItem> - <GridItem w='100%' p={6}> - <Button px={2} py={2} height='fit-content' w='100%' maxH={{base : '50px', lg:'150px'}} bgColor='#334F5B' color='white'> - <Image src="./logo_spotyphie.png" - maxHeight={{ base: "20px", lg: "60px" }} - justifySelf='left' - /> - Title : title<br/> - Author : author - </Button> - </GridItem> - <GridItem w='100%' p={6}> - <Button px={2} py={2} height='fit-content' w='100%' maxH={{base : '50px', lg:'150px'}} bgColor='#334F5B' color='white'> - <Image src="./logo_spotyphie.png" - maxHeight={{ base: "20px", lg: "60px" }} - justifySelf='left' - /> - Title : title<br/> - Author : author - </Button> - </GridItem> - <GridItem w='100%' p={6}> - <Button px={2} py={2} height='fit-content' w='100%' maxH={{base : '50px', lg:'150px'}} bgColor='#334F5B' color='white'> - <Image src="./logo_spotyphie.png" - maxHeight={{ base: "20px", lg: "60px" }} - justifySelf='left' - /> - Title : title<br/> - Author : author - </Button> - </GridItem> + <Grid + templateColumns={{ base: 'repeat(1, 2fr)', lg: 'repeat(3,2fr)' }} + columnGap={6} + w="80%" + > + {searchRenderer} </Grid> </Flex> + {search !== '' ? (window.location.href = `/referral?title=${search}`) : null} </Center> + </> + ); +}; - </> - ) - } - -} - -export default Referral; \ No newline at end of file +export default Referral; diff --git a/src/pages/User/User.tsx b/src/pages/User/User.tsx index 7e4c4e0b781437ad12ca5b0efc9db41de2368780..dd5725428892f7f0769ca7a6667dba8348eb1b9e 100644 --- a/src/pages/User/User.tsx +++ b/src/pages/User/User.tsx @@ -112,6 +112,7 @@ class User extends React.Component<any,any> { if (res.status === 200) { if(res.data.isValid){ alert('Referral Code Verified!'); + localStorage.setItem('referral', "true"); window.location.href = '/referral'; } else{