Skip to content

Commit

Permalink
⚡ develop merged
Browse files Browse the repository at this point in the history
  • Loading branch information
Joliwood committed May 29, 2024
2 parents 0788732 + 345ad58 commit aa60689
Show file tree
Hide file tree
Showing 13 changed files with 228 additions and 40 deletions.
5 changes: 4 additions & 1 deletion public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@
"SEARCH_BAR_BTN": "Search",
"SEARCH_BAR_FILTER_ALBUM": "Albums",
"SEARCH_BAR_FILTER_DURATION_TEXT": "Duration :",
"SEARCH_BAR_FILTER_RELEASE_TEXT": "Years :",
"SEARCH_BAR_FILTER_SONG": "Songs",
"SEARCH_BAR_PLACEHOLDER": "Search by...",
"SEARCH_BAR_TEXT": "What would you like to listen to ?"
"SEARCH_BAR_TEXT": "What would you like to listen to ?",
"SEARCH_RADIO_INPUT_TEXT": "Show all",
"SEARCH_RESULT_NULL": "No result found"
}
7 changes: 5 additions & 2 deletions public/locales/fr/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@
"ORDER_SELECT_TEXT": "Trier par :",
"SEARCH_BAR_BTN": "Chercher",
"SEARCH_BAR_FILTER_ALBUM": "Albums",
"SEARCH_BAR_FILTER_DURATION_TEXT": "Durée",
"SEARCH_BAR_FILTER_DURATION_TEXT": "Durée :",
"SEARCH_BAR_FILTER_RELEASE_TEXT": "Années :",
"SEARCH_BAR_FILTER_SONG": "Chansons",
"SEARCH_BAR_PLACEHOLDER": "Chercher par...",
"SEARCH_BAR_TEXT": "Quelle voulez-vous écouter ?"
"SEARCH_BAR_TEXT": "Quelle voulez-vous écouter ?",
"SEARCH_RADIO_INPUT_TEXT": "Voir tout",
"SEARCH_RESULT_NULL": "Aucun résultat trouvé"
}
16 changes: 14 additions & 2 deletions src/components/customElements/FilterRadio.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
import React from 'react';
import { ReleaseYear, DurationRange } from '../../types/__generated_schemas__/graphql';

interface Props {
inputId: string;
labelText: string;
value?: ReleaseYear | DurationRange;
setFilter: React.Dispatch<React.SetStateAction<any>>;
}

function FilterRadio({ inputId, labelText }: Props): JSX.Element {
function FilterRadio({
inputId, labelText, value, setFilter,
}: Props): JSX.Element {
return (
<div className="form-control">
<label htmlFor={inputId} className="label cursor-pointer">
<span className="label-text px-2 font-semibold text-xs min-[860px]:text-sm">{labelText}</span>
<input id={inputId} type="radio" name="radio-10" className="radio radio-xs min-[860px]:radio-sm bg-base-200" />
<input
id={inputId}
type="radio"
name="radio-10"
value={value}
className="radio radio-xs min-[860px]:radio-sm bg-base-200"
onChange={() => setFilter(value)}
/>
</label>
</div>
);
Expand Down
7 changes: 5 additions & 2 deletions src/components/listenPage/AlbumDisplay.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import React, { useEffect, useMemo, useState } from 'react';
import { AlbumCard } from '../customElements';
import { ListenPageAlbumsQueryQuery } from '../../types/__generated_schemas__/graphql';
import { useTranslation } from 'react-i18next';

import ProfileUpdateAlbum from '../profilePage/ProfileUpdateAlbum';
import { AlbumCard } from '../customElements';
import type { ListenPageAlbumsQueryQuery } from '../../types/__generated_schemas__/graphql';

interface Props {
albums: ListenPageAlbumsQueryQuery['albums'];
Expand All @@ -15,6 +17,7 @@ function AlbumDisplay({
sortBy,
}: Props) {
const [sortedAlbums, setSortedAlbums] = useState<ListenPageAlbumsQueryQuery['albums']>([]);
const { t } = useTranslation('common');

Check failure on line 20 in src/components/listenPage/AlbumDisplay.tsx

View workflow job for this annotation

GitHub Actions / build (20.x)

't' is assigned a value but never used

// The useEffect is used to make a new array of songs based on the sortBy value.
// This array is sorted based on the value of sortBy.
Expand Down
14 changes: 13 additions & 1 deletion src/components/listenPage/Listen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,21 @@ import { ScrollToTopButton, SongAndAlbumOrder, Spinner } from '../customElements
import { ChosenDisplay } from '../../types';
import SearchBar from './SearchBar';
import { ListenPageSongsQuery } from '../../requests/queries';
import { ListenPageSongsQueryQuery, ListenPageAlbumsQueryQuery } from '../../types/__generated_schemas__/graphql';
import type {
ListenPageSongsQueryQuery,
ListenPageAlbumsQueryQuery,
DurationRange,
ReleaseYear,
} from '../../types/__generated_schemas__/graphql';

function Listen({ isLogin }: { isLogin: boolean }) {
const { data, loading, error } = useQuery(ListenPageSongsQuery, { variables: { limit: 30 } });
const [songs, setSongs] = useState<ListenPageSongsQueryQuery['songs']>([]);
const [albums, setAlbums] = useState<ListenPageAlbumsQueryQuery['albums']>([]);
const [chosenDisplay, setChosenDisplay] = useState<ChosenDisplay>('songs');
const [sortBy, setSortBy] = useState<string | null>(null);
const [durationFilter, setDurationFilter] = useState<DurationRange>();
const [yearFilter, setYearFilter] = useState<ReleaseYear>();

useEffect(() => {
if (data?.songs !== undefined) {
Expand All @@ -39,7 +46,12 @@ function Listen({ isLogin }: { isLogin: boolean }) {
<SearchBar
chosenDisplay={chosenDisplay}
setChosenDisplay={setChosenDisplay}
setSongs={setSongs}
setAlbums={setAlbums}
setYearFilter={setYearFilter}
setDurationFilter={setDurationFilter}
yearFilter={yearFilter}
durationFilter={durationFilter}
/>
<SongAndAlbumOrder setSortBy={setSortBy} chosenDisplay={chosenDisplay} />

Expand Down
145 changes: 115 additions & 30 deletions src/components/listenPage/SearchBar.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,40 @@
import React, { useMemo } from 'react';
import React, { useState, useMemo } from 'react';
import { useLazyQuery } from '@apollo/client';
import { useTranslation } from 'react-i18next';

import { Logo } from '../../svg';
import { FilterRadio } from '../customElements';
import { ChosenDisplay } from '../../types';
import { ListenPageAlbumsQuery } from '../../requests/queries';
import { ListenPageAlbumsQueryQuery } from '../../types/__generated_schemas__/graphql';
import PageTitle from '../customElements/PageTitle';
import { ListenPageAlbumsQuery, SearchAlbumsQuery, SearchSongsQuery } from '../../requests/queries';
import {
type ListenPageAlbumsQueryQuery,
type ListenPageSongsQueryQuery,
ReleaseYear,
DurationRange,
} from '../../types/__generated_schemas__/graphql';

interface Props {
chosenDisplay: string;
chosenDisplay: 'songs' | 'albums';
setChosenDisplay: React.Dispatch<React.SetStateAction<ChosenDisplay>>;
setAlbums: React.Dispatch<React.SetStateAction<ListenPageAlbumsQueryQuery['albums']>>;
setSongs: React.Dispatch<React.SetStateAction<ListenPageSongsQueryQuery['songs']>>;
setYearFilter: React.Dispatch<React.SetStateAction<ReleaseYear | undefined>>;
setDurationFilter: React.Dispatch<React.SetStateAction<DurationRange | undefined>>;
yearFilter?: ReleaseYear;
durationFilter?: DurationRange;
}

function SearchBar({ chosenDisplay, setChosenDisplay, setAlbums }: Props): JSX.Element {
function SearchBar({
chosenDisplay,
setChosenDisplay,
setAlbums,
setSongs,
setDurationFilter,
setYearFilter,
yearFilter,
durationFilter,
}: Props): JSX.Element {
const { t } = useTranslation('common');
const [nameFilter, setNameFilter] = useState('');

const [getAlbums] = useLazyQuery(ListenPageAlbumsQuery, {
variables: { limit: 15 },
Expand All @@ -27,41 +46,111 @@ function SearchBar({ chosenDisplay, setChosenDisplay, setAlbums }: Props): JSX.E
},
});

const [getFilteredAlbums] = useLazyQuery(SearchAlbumsQuery, {
onCompleted: (data) => {
if (data.albums) {
setAlbums(data.albums);
setChosenDisplay('albums');
}
},
});

const [getFilteredSongs] = useLazyQuery(SearchSongsQuery, {
onCompleted: (data) => {
if (data.songs) {
setSongs(data.songs);
setChosenDisplay('songs');
}
},
});

const handleSearch = () => {
if (chosenDisplay === 'albums') {
getFilteredAlbums({
variables: {
limit: 15,
filter: { name: nameFilter, release_year: yearFilter },
},
});
}
if (chosenDisplay === 'songs') {
getFilteredSongs({
variables: {
limit: 30,
filter: { name: nameFilter, duration_filter: durationFilter },
},
});
}
};

// Function to change the display between songs and albums and reload the data without filters
const handleDisplayChanges = (display: ChosenDisplay) => {
setChosenDisplay(display);
setNameFilter('');
if (display === 'albums') getAlbums({ variables: { limit: 15 } });
if (display === 'songs') getFilteredSongs({ variables: { limit: 30 } });
};

const songDuration = useMemo(() => {
if (chosenDisplay === 'albums') {
return (
<div className="flex gap-4">
<FilterRadio inputId="duration-album-all" labelText="Show all" />
<FilterRadio inputId="duration-album-min" labelText="- 30 mn" />
<FilterRadio inputId="duration-album-mid" labelText="30 - 60 mn" />
<FilterRadio inputId="duration-album-max" labelText="+ 60 mn" />
<div className="flex flex-col gap-4">
<div className="font-semibold text-sm pl-3 min-[540px]:text-base">{t('SEARCH_BAR_FILTER_RELEASE_TEXT')}</div>
<div className="flex gap-4 flex-wrap justify-center">
<FilterRadio inputId="release-album-all" labelText={t('SEARCH_RADIO_INPUT_TEXT')} setFilter={setYearFilter} />
<FilterRadio inputId="release-album-min" labelText="70's" value={ReleaseYear.Year_70} setFilter={setYearFilter} />
<FilterRadio inputId="release-album-mid" labelText="80's" value={ReleaseYear.Year_80} setFilter={setYearFilter} />
<FilterRadio inputId="release-album-max" labelText="90's" value={ReleaseYear.Year_90} setFilter={setYearFilter} />
<FilterRadio inputId="release-album-mid" labelText="2000's" value={ReleaseYear.Year_2000} setFilter={setYearFilter} />
<FilterRadio inputId="release-album-max" labelText="2010's" value={ReleaseYear.Year_2010} setFilter={setYearFilter} />
</div>
</div>
);
}
return (
<div className="flex gap-4">
<FilterRadio inputId="duration-song-all" labelText="Show all" />
<FilterRadio inputId="duration-song-min" labelText="- 1mn" />
<FilterRadio inputId="duration-song-mid" labelText="1 - 5 mn" />
<FilterRadio inputId="duration-song-max" labelText="+ 5 mn" />
<div className="flex flex-col gap-4">
<div className="font-semibold text-sm pl-3 min-[540px]:text-base">{t('SEARCH_BAR_FILTER_DURATION_TEXT')}</div>
<div className="flex gap-4 flex-wrap justify-center">
<FilterRadio inputId="duration-song-all" labelText={t('SEARCH_RADIO_INPUT_TEXT')} setFilter={setDurationFilter} />
<FilterRadio inputId="duration-song-min" labelText="- 1mn" value={DurationRange.OneMinute} setFilter={setDurationFilter} />
<FilterRadio inputId="duration-song-mid" labelText="1 - 3 mn" value={DurationRange.OneToThreeMinutes} setFilter={setDurationFilter} />
<FilterRadio inputId="duration-song-mid" labelText="3 - 5 mn" value={DurationRange.ThreeToFiveMinutes} setFilter={setDurationFilter} />
<FilterRadio inputId="duration-song-max" labelText="+ 5 mn" value={DurationRange.MoreThanFiveMinutes} setFilter={setDurationFilter} />
</div>
</div>
);
}, [chosenDisplay]);
}, [chosenDisplay, t, setDurationFilter, setYearFilter]);

const bottomElement = useMemo(() => (
<div className="w-full sm:w-[60%]">
return (
<div className="min-[540px]:w-1/2 pt-32 text-center">
<div className="flex flex-col items-center gap-4 pb-8">
<div className="w-16 h-16 min-[540px]:w-20 min-[540px]:h-20 rounded-full flex items-center justify-center">
<Logo />
</div>
<h1 className="text-2xl min-[540px]:text-4xl font-bold">{t('MENU_APP_NAME')}</h1>
<p className="text-md font-semibold min-[540px]:text-lg">{t('SEARCH_BAR_TEXT')}</p>
</div>
<div className="flex flex-col items-center">

{/* Search input => Filter on the request */}
<div className="join w-full px-2">
<input className="w-full input input-md input-bordered join-item bg-base-200" placeholder={t('SEARCH_BAR_PLACEHOLDER')} />
<button type="button" className="btn btn-md join-item border border-stone-700">{t('SEARCH_BAR_BTN')}</button>
<input
className="w-full input input-md input-bordered join-item bg-base-200"
placeholder={t('SEARCH_BAR_PLACEHOLDER')}
value={nameFilter}
onChange={(e) => setNameFilter(e.target.value)}
/>
<button
type="button"
className="btn btn-md join-item border border-stone-700"
onClick={handleSearch}
>
{t('SEARCH_BAR_BTN')}
</button>
</div>

{/* Duration input => Filter on the request */}
<div className="flex flex-col gap-4 pt-6 items-start min-[860px]:flex-row min-[860px]:items-center">
<div className="font-semibold text-sm pl-3 min-[540px]:text-base">{t('SEARCH_BAR_FILTER_DURATION_TEXT')}</div>

{/* Radio Input Components changing on isAlbum value change */}
{songDuration}
</div>
Expand All @@ -70,25 +159,21 @@ function SearchBar({ chosenDisplay, setChosenDisplay, setAlbums }: Props): JSX.E
<div>
<button
type="button"
onClick={() => setChosenDisplay('songs')}
onClick={handleDisplayChanges.bind(null, 'songs')}
className={`btn btn-sm mx-4 py-3 min-[540px]:btn-md ${chosenDisplay === 'songs' ? 'border-primary my-5 border-2' : 'border-stone-700 my-6 border'}`}
>
{t('SEARCH_BAR_FILTER_SONG')}
</button>
<button
type="button"
onClick={() => getAlbums({ variables: { limit: 30 } })}
onClick={handleDisplayChanges.bind(null, 'albums')}
className={`btn btn-sm mx-4 py-3 min-[540px]:btn-md ${chosenDisplay === 'albums' ? 'border-primary my-5 border-2' : 'border-stone-700 my-6 border'}`}
>
{t('SEARCH_BAR_FILTER_ALBUM')}
</button>
</div>
</div>
</div>
), [chosenDisplay, getAlbums, setChosenDisplay, songDuration, t]);

return (
<PageTitle title={t('MENU_APP_NAME')} bottomElement={bottomElement} />
);
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/listenPage/SongDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ interface Props {
function SongDisplay({
fromProfilePage = false,
isLogin,
likable = false,
likable = true,
songs,
sortBy,
}: Props) {
Expand Down
1 change: 0 additions & 1 deletion src/components/profilePage/ProfileUpdateSong.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -194,5 +194,4 @@ const ProfileUpdateSong = (props: Props): JSX.Element => {
</>
);
};

export default ProfileUpdateSong;
22 changes: 22 additions & 0 deletions src/requests/queries/SearchAlbumsQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { gql } from '../../types/__generated_schemas__/gql';

const SearchAlbumsQuery = gql(`
query SearchAlbumsQuery($limit: Int, $filter: AlbumFilterInput) {
albums(limit: $limit, filter: $filter) {
id
title
artist {
name
}
cover
release_year
songs {
id
title
duration
}
}
}
`);

export default SearchAlbumsQuery;
19 changes: 19 additions & 0 deletions src/requests/queries/SearchSongsQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { gql } from '../../types/__generated_schemas__/gql';

const SearchSongsQuery = gql(`
query SearchSongsQuery($limit: Int, $filter: SongFilterInput) {
songs(limit: $limit, filter: $filter) {
id
title
artist {
name
}
cover
duration
release_year
isLiked
}
}
`);

export default SearchSongsQuery;
2 changes: 2 additions & 0 deletions src/requests/queries/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ export { default as ListenPageSongsQuery } from './ListenPageSongsQuery';
export { default as LoginQuery } from './LoginQuery';
export { default as ProfileAlbums } from './ProfileAlbums';
export { default as ProfileQuery } from './ProfileQuery';
export { default as SearchSongsQuery } from './SearchSongsQuery';
export { default as SearchAlbumsQuery } from './SearchAlbumsQuery';
export { default as ProfileSongs } from './ProfileSongs';
export { default as SongOverviewQuery } from './SongOverviewQuery';
export { default as UserSongsQuery } from './UserSongsQuery';
Loading

0 comments on commit aa60689

Please sign in to comment.