Upgrade spot screen and navbar 🎨
continuous-integration/drone/push Build is passing Details

pull/19/head
Emre KARTAL 1 year ago
parent e86a35118d
commit ae0ff4e455

@ -97,7 +97,7 @@ Tout d'abord, il faut fournir votre *adresse e-mail* et votre *nom Spotify* aux
<div align = center>
<img src="doc/Images/Real_RegisterPage.png" width="250" >
<img src="doc/Maquettes/RegisterPage.png" width="200" >
</div>
@ -108,10 +108,7 @@ Vous serez normalement redirigé sur la page Spotify où vous devrez vous connec
<div align = center>
<img src="doc/Images/Real_HomePage.png" width="250" >
<img src="doc/Images/Real_FavoritePage.png" width="250" >
<img src="doc/Images/Real_ConversationPage.png" width="250" >
<img src="doc/Images/Real_SettingPage.png" width="250" >
<img src="doc/Images/Overview.png">
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 898 KiB

@ -148,8 +148,6 @@ class UserController implements IController {
* description: Users information retrieved successfully
* 401:
* description: Unauthorized - Invalid or missing authentication token
* 400:
* description: Bad request - Invalid input data
*/
this.router.get(`${this.path}s`, authenticator, this.getUsers);
@ -525,7 +523,7 @@ class UserController implements IController {
const userIds = req.query.ids as string;
if (!userIds) {
return res.status(400).json({ message: 'Please provide user ids' });
return res.status(200).json([]);
}
const userIdArray = userIds.split('&');

@ -21,7 +21,7 @@ class LocationService {
snapshot.forEach(location => {
const distance = this.distanceBetween(latitude, longitude, location.latitude, location.longitude);
if (distance <= 1000) {
usersLocation.push(new UserLocation(location._id, location.userId, location.musicId, Math.ceil(distance / 200) * 200, location.updatedAt));
usersLocation.push(new UserLocation(location._id, location.userId, location.musicId, Math.ceil(distance + 0.1 / 200) * 200, location.updatedAt));
}
});
return { data: usersLocation };

@ -26,7 +26,7 @@ export default function Friend(props: FriendProps) {
paddingVertical: 9,
},
image: {
marginLeft: 15,
marginLeft: "7%",
marginRight: 12,
width: 55,
height: 55,
@ -51,7 +51,7 @@ export default function Friend(props: FriendProps) {
},
time: {
fontSize: normalize(18),
color: '#989898'
color: style.Text
},
profilContainer: {
marginTop: 5,

@ -0,0 +1,84 @@
import React from 'react';
import { StyleSheet, Text, View, Image } from 'react-native';
import normalize from './Normalize';
type UserInfoProps = {
image: string,
date: Date,
distance: string,
}
export default function UserInfoBadge(props: UserInfoProps) {
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
height: 30,
paddingHorizontal: normalize(10),
backgroundColor: '#3F1DC3',
alignSelf: 'flex-start',
borderRadius: 12,
paddingRight: 20,
},
section: {
flexDirection: 'row',
alignItems: 'center',
},
image: {
width: normalize(26),
height: normalize(26),
borderRadius: 30,
marginRight: normalize(10),
},
text: {
fontSize: normalize(14),
color: '#FFFFFF',
},
boldText: {
fontWeight: 'bold',
},
});
const date = formatDate(props.date);
return (
<View style={styles.container}>
<Image source={{ uri: props.image }} style={styles.image} />
<Text style={styles.text}>Il y a </Text>
{date.days !== 0 ? (
<View style={styles.section}>
<Text style={[styles.text, styles.boldText]}>{date.days}</Text>
<Text style={styles.text}>j </Text>
</View>
) : date.hours !== 0 ? (
<View style={styles.section}>
<Text style={[styles.text, styles.boldText]}>{date.hours}</Text>
<Text style={styles.text}>h </Text>
</View>
) : (
<View style={styles.section}>
<Text style={[styles.text, styles.boldText]}>{date.minutes}</Text>
<Text style={styles.text}>min</Text>
</View>
)}
<Text style={styles.text}> {'<'} </Text>
<Text style={[styles.text, styles.boldText]}>{props.distance}</Text>
<Text style={styles.text}>m</Text>
</View>
);
}
const formatDate = (date: Date) => {
const now = new Date();
const diffInMilliseconds = now.getTime() - date.getTime();
const diffInSeconds = Math.floor(diffInMilliseconds / 1000);
const diffInMinutes = Math.floor(diffInSeconds / 60);
const diffInHours = Math.floor(diffInMinutes / 60);
const diffInDays = Math.floor(diffInHours / 24);
const days = Math.floor(diffInDays);
const hours = Math.floor(diffInHours % 24);
const minutes = Math.floor(diffInMinutes % 60);
return { days, hours, minutes };
};

@ -1,7 +1,7 @@
export default [
{
id: '1',
title: 'Bienvenue sur Flad',
title: 'Bienvenue sur Flad 🎶',
description: 'L\'application pour découvrir de nouvelles musiques et vous faire de nouveaux amis',
image: require('../assets/images/board_1.png')
},

@ -1,15 +1,18 @@
import Music from "./Music";
import { Person } from "./Person";
export class Spot {
private _id: string;
private _user: string;
private _user: Person;
private _music: Music;
public distance: string;
private _date: Date;
constructor(id: string, user: string, music: Music, date: Date) {
constructor(id: string, user: Person, music: Music, distance: string, date: Date) {
this._id = id;
this._user = user;
this._music = music;
this.distance = distance;
this._date = date;
}
@ -21,11 +24,11 @@ export class Spot {
this._id = value;
}
get user(): string {
get user(): Person {
return this._user;
}
set user(value: string) {
set user(value: Person) {
this._user = value;
}

@ -0,0 +1,7 @@
import { Person } from "../Person";
export class PersonMapper {
public static toModel(person: any): Person {
return new Person(person._id, person.name, person.image);
}
}

@ -2,6 +2,6 @@ import { Spot } from "../Spot";
export class SpotMapper {
public static toModel(spot: any): Spot {
return new Spot(spot._id, spot.userId, spot.music, new Date(spot.date));
return new Spot(spot._id, spot.user, spot.music, spot.distance, new Date(spot.date));
}
}

@ -1,23 +1,21 @@
import React, { useEffect, useState } from 'react';
import { View, StyleSheet, Platform, Alert } from 'react-native';
import { View, Alert } from 'react-native';
import { faUser, faEnvelope, faHeart, faMusic } from "@fortawesome/free-solid-svg-icons"
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { NavigationContainer } from '@react-navigation/native';
import { NavigationContainer, DefaultTheme, DarkTheme } from '@react-navigation/native';
import FavoriteNavigation from './FavoriteNavigation';
import SettingNavigation from './SettingNavigation';
import normalize from '../components/Normalize';
// @ts-ignore
import FontAwesome from 'react-native-vector-icons/FontAwesome';
import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome";
import SpotNavigation from './SpotNavigation';
import MessagingNavigation from './MessagingNavigation';
import { useDispatch, useSelector } from 'react-redux';
import { colorsDark } from '../constants/colorsDark';
import { colorsLight } from '../constants/colorsLight';
import { getUserCurrentMusic } from '../redux/thunk/appThunk';
import { logout } from '../redux/thunk/authThunk';
import { setAccessError, setErrorEmptyMusic } from '../redux/actions/userActions';
import * as Location from 'expo-location';
import { getSpotList } from '../redux/thunk/spotThunk';
import Music from '../models/Music';
import normalize from '../components/Normalize';
export default function HomeNavigation() {
//@ts-ignore
@ -32,17 +30,7 @@ export default function HomeNavigation() {
const currentMusic: Music = useSelector(state => state.appReducer.userCurrentMusic);
const [locationPermission, setLocationPermission] = useState(false);
const style = isDark ? colorsDark : colorsLight;
const BottomTabNavigator = createBottomTabNavigator();
const MyTheme = {
dark: false,
colors: {
primary: 'rgb(255, 45, 85)',
card: style.Card,
border: style.Card,
text: 'rgb(138, 138, 138)',
}
};
const dispatch = useDispatch();
@ -128,38 +116,44 @@ export default function HomeNavigation() {
return (
// @ts-ignore
<NavigationContainer theme={MyTheme}>
<NavigationContainer theme={isDark ? DarkTheme : DefaultTheme}>
<BottomTabNavigator.Navigator
initialRouteName="Spots"
screenOptions={{
tabBarStyle: styles.tabBar,
...(Platform.OS === 'android'
? { tabBarLabelStyle: { bottom: normalize(10) } }
: { tabBarLabelStyle: { bottom: normalize(-25) } }
),
tabBarActiveTintColor: isDark ? "white" : "rgb(255, 45, 85)",
tabBarStyle: {
backgroundColor: isDark ? "rgb(46,46,46)" : "white",
},
}}>
<BottomTabNavigator.Screen name="Spots" component={SpotNavigation}
options={{
headerShown: false,
tabBarIcon: ({ color }) => <View style={styles.IconContainer}><TabBarIcon name="music" color={color} /></View>,
tabBarIcon: ({ color }) => <TabBarIcon name={faMusic} color={color} size={23} />,
}} />
<BottomTabNavigator.Screen name="Favorites" component={FavoriteNavigation}
options={{
tabBarBadge: favoritesMusicLength,
tabBarBadgeStyle: { backgroundColor: 'yellow' },
tabBarBadgeStyle: {
backgroundColor: 'yellow',
maxWidth: 12.5,
marginTop: 3,
maxHeight: 13,
borderRadius: 7,
fontSize: normalize(10),
lineHeight: 12,
},
headerShown: false,
tabBarIcon: ({ color }) => <View style={styles.IconContainer}><TabBarIcon name="heart" color={color} /></View>,
tabBarIcon: ({ color }) => <View><TabBarIcon name={faHeart} color={color} size={23} /></View>,
}} />
<BottomTabNavigator.Screen name="Messages" component={MessagingNavigation}
options={{
headerShown: false,
tabBarIcon: ({ color }) => <View style={styles.IconContainer}><TabBarIcon name="comment" color={color} /></View>,
tabBarIcon: ({ color }) => <View ><TabBarIcon name={faEnvelope} color={color} size={23} /></View>,
}} />
<BottomTabNavigator.Screen name="Settings" component={SettingNavigation}
<BottomTabNavigator.Screen name="Profil" component={SettingNavigation}
options={{
headerShown: false,
tabBarIcon: ({ color }) => <View style={styles.IconContainer}><TabBarIcon name="cog" color={color} /></View>,
tabBarIcon: ({ color, size }) => <TabBarIcon name={faUser} color={color} size={23} />,
}} />
</BottomTabNavigator.Navigator>
</NavigationContainer>
@ -167,22 +161,9 @@ export default function HomeNavigation() {
}
function TabBarIcon(props: {
name: React.ComponentProps<typeof FontAwesome>['name'];
name: any;
color: string;
size: number;
}) {
return <FontAwesome size={30} {...props} />;
}
const styles = StyleSheet.create({
tabBar: {
height: 60,
position: 'absolute',
bottom: normalize(50),
borderRadius: 30,
marginHorizontal: 25
},
IconContainer: {
position: 'absolute',
top: 6,
}
})
return <FontAwesomeIcon icon={props.name} style={{ marginBottom: -5 }} size={props.size} color={props.color} />;
}

@ -13,7 +13,7 @@ export default function SettingNavigation() {
options={{ headerShown: false }}
/>
<Stack.Screen
name="Profil"
name="Account"
component={ProfilScreen}
options={{ headerShown: false }}
/>

@ -8,6 +8,8 @@
"web": "expo start --web"
},
"dependencies": {
"@fortawesome/free-solid-svg-icons": "^6.5.1",
"@fortawesome/react-native-fontawesome": "^0.3.0",
"@react-native-async-storage/async-storage": "~1.17.3",
"@react-navigation/bottom-tabs": "^6.5.4",
"@react-navigation/native": "^6.1.4",

@ -15,4 +15,17 @@ export const setFavoriteMusic = (spots: Spot[]) => {
type: favoritesTypes.GET_FAVORITE_MUSICS,
payload: spots,
};
}
export const addFavoriteMusic = (spot: Spot) => {
return {
type: favoritesTypes.ADD_FAVORITE_MUSICS,
payload: spot,
};
}
export const resetNbAddedFavoriteMusic = () => {
return {
type: favoritesTypes.RESET_NB_ADDED_FAVORITE_MUSIC
};
}

@ -8,25 +8,37 @@ const initialState = {
spot: [] as Spot[],
favoriteMusic: [] as Spot[],
userCurrentMusic: null,
nbAddedFavoriteMusic: 0
nbAddedFavoriteMusic: 0,
oldSpot: [] as String[],
}
const appReducer = (state = initialState, action: any) => {
switch (action.type) {
case favoritesTypes.GET_FAVORITE_MUSICS:
return { ...state, favoriteMusic: action.payload };
case favoritesTypes.ADD_FAVORITE_MUSICS:
return {
...state, favoriteMusic: [...state.favoriteMusic, action.payload],
nbAddedFavoriteMusic: state.nbAddedFavoriteMusic + 1
};
case favoritesTypes.RESET_NB_ADDED_FAVORITE_MUSIC:
return { ...state, nbAddedFavoriteMusic: 0 };
case spotTypes.FETCH_SPOT:
const uniqueSpots = action.payload.filter((spot: Spot) => {
return !state.spot.some((s) => s.user === spot.user && s.music.id === spot.music.id);
const spotKey = `${spot.user}_${spot.music.id}`;
return !state.oldSpot.includes(spotKey);
});
const updatedSpotList = [...uniqueSpots, ...state.spot];
return { ...state, spot: updatedSpotList };
const updatedOldSpotList = [...state.oldSpot, ...uniqueSpots.map((spot: Spot) => `${spot.user}_${spot.music.id}`)];
return { ...state, spot: updatedSpotList, oldSpot: updatedOldSpotList };
case spotTypes.REMOVE_SPOT:
return { ...state, spot: state.spot.filter((spot) => spot.user !== action.payload.user && spot.music.id !== action.payload.music.id) };
case spotifyTypes.GET_USER_CURRENT_MUSIC:
return { ...state, userCurrentMusic: action.payload };
case userTypes.USER_LOGOUT:
return { ...state, spot: [], favoriteMusic: [], userCurrentMusic: null, nbAddedFavoriteMusic: 0 };
return { ...state, spot: [], favoriteMusic: [], userCurrentMusic: null, nbAddedFavoriteMusic: 0, oldSpot: [] };
default:
return state;
}

@ -13,6 +13,7 @@ const store = configureStore({
reducer: reducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
immutableCheck: false,
serializableCheck: false,
})
},);

@ -3,9 +3,11 @@ import * as SecureStore from 'expo-secure-store';
import { Spot } from "../../models/Spot";
import configs from "../../constants/config";
import { MusicServiceProvider } from "../../models/MusicServiceProvider";
import { setFavoriteMusic, setUserCurrentMusic } from "../actions/appActions";
import { addFavoriteMusic, setFavoriteMusic, setUserCurrentMusic } from "../actions/appActions";
import { setAccessError, setErrorEmptyMusic } from "../actions/userActions";
import { SpotMapper } from "../../models/mapper/SpotMapper";
import { logout } from "./authThunk";
import { removeFromSpotList } from "../actions/spotActions";
export const getUserCurrentMusic = () => {
//@ts-ignore
@ -27,6 +29,9 @@ export const getUserCurrentMusic = () => {
dispatch(setUserCurrentMusic(music))
} catch (error: any) {
switch (error.response.status) {
case 401:
dispatch(logout);
break;
case 403:
dispatch(setAccessError(true));
break;
@ -39,13 +44,6 @@ export const getUserCurrentMusic = () => {
}
}
export const addFavoriteMusic = (spot: Spot) => {
//@ts-ignore
return async dispatch => {
};
}
export const getFavoriteMusic = () => {
//@ts-ignore
return async dispatch => {
@ -71,11 +69,38 @@ export const getFavoriteMusic = () => {
};
});
dispatch(setFavoriteMusic(result.map((item: any) => SpotMapper.toModel(item))));
dispatch(setFavoriteMusic(result.map((item: any) => SpotMapper.toModel(item))));
} catch (error: any) {
console.error(error);
dispatch(setAccessError(true));
}
};
}
}
export const addMusicToFavorite = (spot: Spot) => {
//@ts-ignore
return async dispatch => {
try {
dispatch(removeFromSpotList(spot));
let token: string | null = await SecureStore.getItemAsync(configs.key);
const headers = {
'Authorization': 'Bearer ' + token
};
const body = {
"musicId": spot.music.id,
"userId": spot.user
}
await axios.post(configs.API_URL + '/user/musics', body, { headers });
spot.date = new Date(Date.now());
dispatch(addFavoriteMusic(spot));
} catch (error: any) {
switch (error.response.status) {
default:
console.error("Error like spot : " + error);
break;
}
}
};
}

@ -2,9 +2,13 @@ import axios from "axios";
import configs from "../../constants/config";
import * as SecureStore from 'expo-secure-store';
import qs from "qs";
import { setSpotList } from "../actions/spotActions";
import { removeFromSpotList, setSpotList } from "../actions/spotActions";
import { MusicServiceProvider } from "../../models/MusicServiceProvider";
import { SpotMapper } from "../../models/mapper/SpotMapper";
import { Spot } from "../../models/Spot";
import { Person } from "../../models/Person";
import Music from "../../models/Music";
import { PersonMapper } from "../../models/mapper/PersonMapper";
export const getSpotList = (longitude: string, latitude: string, music: string) => {
//@ts-ignore
@ -26,18 +30,27 @@ export const getSpotList = (longitude: string, latitude: string, music: string)
const musicIds = resp.data.data.map((music: any) => music.musicId);
const musics = await MusicServiceProvider.musicService.getMusicsWithIds(musicIds);
const userIds = resp.data.data.map((user: any) => user.userId);
const users = await getUsersInfo(userIds);
const result = resp.data.data
.filter((spot: any) => musics.some((m: any) => m.id === spot.musicId))
.filter((spot: any) => musics.some((m: Music) => m.id === spot.musicId))
.filter((spot: any) => users.some((u: Person) => u.id === spot.userId))
.map((spot: any) => {
const matchingMusic = musics.find((m: any) => m.id === spot.musicId);
const matchingUser = users.find((user: any) => user.id === spot.userId);
return {
...spot,
music: matchingMusic,
user: matchingUser,
};
});
dispatch(setSpotList(result.map((item: any) => SpotMapper.toModel(item))));
} catch (error: any) {
console.log(error);
switch (error.response.status) {
default:
console.error("Error retrieving spots : " + error);
@ -46,4 +59,40 @@ export const getSpotList = (longitude: string, latitude: string, music: string)
}
}
}
const getUsersInfo = async (userIds: string[]) => {
try {
const token: string | null = await SecureStore.getItemAsync(configs.key);
const ids = userIds.join('&');
const resp = await axios({
url: configs.API_URL + `/users?ids=${ids}`,
method: 'GET',
headers: {
Authorization: `Bearer ${token}`,
},
});
return resp.data.map((item: any) => PersonMapper.toModel(item));
} catch (error) {
console.error("Error retrieving user information: " + error);
return [];
}
}
export const removeSpot = (spot: Spot) => {
//@ts-ignore
return async dispatch => {
dispatch(removeFromSpotList(spot));
}
}
export const addToPlaylist = (spot: Spot) => {
//@ts-ignore
return async dispatch => {
MusicServiceProvider.musicService.addToPlaylist(spot.music.id);
dispatch(removeFromSpotList(spot));
}
}

@ -1,4 +1,5 @@
export const favoritesTypes = {
GET_FAVORITE_MUSICS: 'GET_FAVORITE_MUSICS',
ADD_FAVORITE_MUSICS: 'ADD_FAVORITE_MUSICS',
RESET_NB_ADDED_FAVORITE_MUSIC: 'RESET_NB_ADDED_FAVORITE_MUSIC',
}

@ -32,8 +32,7 @@ export default function ConversationScreen() {
paddingTop: insets.top
},
titleContainer: {
marginTop: 10,
marginLeft: 20,
marginLeft: "7%",
},
title: {
fontSize: normalize(28),
@ -41,7 +40,7 @@ export default function ConversationScreen() {
color: style.Text,
},
description: {
marginTop: 10,
marginTop: 3,
fontSize: normalize(20),
color: '#787878',
marginBottom: 5
@ -52,7 +51,7 @@ export default function ConversationScreen() {
<SafeAreaView style={styles.mainSafeArea}>
<View style={styles.titleContainer}>
<Text style={styles.title}>Messages</Text>
<Text style={styles.description}>Retrouvez ici tous vos amis!</Text>
<Text style={styles.description}>Retrouvez ici les discussions</Text>
</View>
<FlatList
style={{ marginTop: 10 }}

@ -1,5 +1,5 @@
import React, { useEffect } from 'react';
import { StyleSheet, Text, View, FlatList, SafeAreaView, SectionList, TouchableOpacity } from 'react-native';
import React, { useEffect, useState } from 'react';
import { StyleSheet, Text, View, FlatList, SafeAreaView, SectionList, TouchableOpacity, RefreshControl } from 'react-native';
import CardMusic from '../components/CardMusicComponent';
import normalize from '../components/Normalize';
import { Svg, Path } from 'react-native-svg';
@ -11,12 +11,15 @@ import { colorsLight } from '../constants/colorsLight';
import { getFavoriteMusic } from '../redux/thunk/appThunk';
import { Spot } from '../models/Spot';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { resetNbAddedFavoriteMusic } from '../redux/actions/appActions';
import { useFocusEffect } from '@react-navigation/native';
export default function FavoriteScreen() {
// @ts-ignore
const isDark = useSelector(state => state.userReducer.dark);
const style = isDark ? colorsDark : colorsLight;
const [refreshing, setRefreshing] = useState(false);
const images = [
{ id: 1, source: require('../assets/images/flady_love.png') },
@ -35,6 +38,21 @@ export default function FavoriteScreen() {
dispatch(getFavoriteMusic());
}, []);
const handleRefresh = () => {
setRefreshing(true);
//@ts-ignore
dispatch(getFavoriteMusic());
setTimeout(() => {
setRefreshing(false);
}, 900);
};
useFocusEffect(
React.useCallback(() => {
dispatch(resetNbAddedFavoriteMusic());
}, [])
);
const groupByDate = (data: Spot[]) => {
const groupedData: { [key: string]: Spot[] } = {};
@ -74,8 +92,8 @@ export default function FavoriteScreen() {
paddingTop: insets.top
},
titleContainer: {
marginVertical: 10,
marginLeft: 20,
marginTop: 5,
marginLeft: "7%",
},
header: {
flexDirection: 'row',
@ -89,7 +107,6 @@ export default function FavoriteScreen() {
color: style.Text,
},
description: {
marginTop: 10,
fontSize: normalize(20),
color: '#787878',
marginBottom: 5
@ -97,9 +114,13 @@ export default function FavoriteScreen() {
titleSection: {
fontSize: normalize(20),
color: style.Text,
fontWeight: 'medium',
marginLeft: 20,
fontWeight: '500',
marginLeft: "7%",
marginBottom: 10
},
collection: {
marginTop: "3%",
marginLeft: "1%",
}
});
@ -116,8 +137,16 @@ export default function FavoriteScreen() {
<Text style={styles.description}>Retrouvez ici vos musiques favorites</Text>
</View>
<SectionList
style = {styles.collection}
sections={groupByDate(favoriteMusic)}
keyExtractor={(item: Spot) => item.music.id}
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={handleRefresh}
tintColor={style.Text}
/>
}
keyExtractor={(item: Spot) => item.music.id + item.user + item.date}
renderItem={({ item }) => (
<TouchableOpacity
onPress={() => {

@ -34,7 +34,7 @@ export default function LoginScreen() {
const submitForm = () => {
const credentials: LoginCredentials = {
email: username.toLowerCase(),
email: username.toLowerCase().trim(),
password: password
};
//@ts-ignore

@ -291,7 +291,7 @@ export default function SettingScreen() {
<TouchableOpacity
// @ts-ignore
onPress={() => navigation.navigate('Profil')}
onPress={() => navigation.navigate('Account')}
>
<View style={styles.profil}>
<Image source={{ uri: currentUser.image }} style={styles.imageProfil} />

@ -12,6 +12,9 @@ import { removeFromSpotList } from '../redux/actions/spotActions';
import { MusicServiceProvider } from '../models/MusicServiceProvider';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import Artist from '../models/Artist';
import { addMusicToFavorite } from '../redux/thunk/appThunk';
import { addToPlaylist, removeSpot } from '../redux/thunk/spotThunk';
import UserInfoBadge from '../components/UserInfoBadgeComponent';
export default function SpotScreen() {
//@ts-ignore
@ -29,13 +32,15 @@ export default function SpotScreen() {
const onSwipe = (direction: 'left' | 'right' | 'down') => {
if (direction === 'right') {
dispatch(removeFromSpotList(currentCard));
//@ts-ignore
dispatch(addMusicToFavorite(currentCard));
} else if (direction === 'left') {
dispatch(removeFromSpotList(currentCard));
//@ts-ignore
dispatch(removeSpot(currentCard));
}
else if (direction === 'down') {
MusicServiceProvider.musicService.addToPlaylist(currentCard.music.id);
dispatch(removeFromSpotList(currentCard));
//@ts-ignore
dispatch(addToPlaylist(currentCard));
}
};
@ -80,18 +85,18 @@ export default function SpotScreen() {
right: 0,
height: insets.top + 150,
},
header: {
left: width / 11,
top: '2.5%',
},
titleLabel: {
fontStyle: 'normal',
left: width / 9,
top: '5%',
color: "#FFFFFF",
fontSize: normalize(40),
fontWeight: "800",
},
artistLabel: {
fontStyle: 'normal',
left: width / 9,
top: '5%',
color: "#FFFFFF",
fontSize: normalize(20),
},
@ -101,7 +106,7 @@ export default function SpotScreen() {
paddingHorizontal: 30,
width: '100%',
position: "absolute",
top: "74%"
top: "85%"
},
button: {
alignItems: 'center',
@ -114,18 +119,18 @@ export default function SpotScreen() {
},
dislikeIcon: {
resizeMode: "stretch",
height: '44%',
height: '40%',
aspectRatio: 1.05,
},
discoveryIcon: {
resizeMode: "stretch",
height: '50%',
height: '42%',
aspectRatio: 1.5,
marginLeft: '7%'
},
likeIcon: {
resizeMode: "stretch",
height: '50%',
height: '42%',
aspectRatio: 1.1
},
loading: {
@ -152,8 +157,11 @@ export default function SpotScreen() {
}}
/>
<LinearGradient colors={['rgba(2, 2, 2, 0.40) 0%', 'rgba(0, 0, 0, 0) 100%']} style={styles.gradient} />
<Text style={styles.titleLabel}>{currentCard.music.name}</Text>
<Text style={styles.artistLabel}>{currentCard.music.artists.map((artist: Artist) => artist.name).join(', ')}</Text>
<View style={styles.header}>
<UserInfoBadge image={currentCard.user.image} date={currentCard.date} distance={currentCard.distance} />
<Text style={styles.titleLabel}>{currentCard.music.name}</Text>
<Text style={styles.artistLabel}>{currentCard.music.artists.map((artist: Artist) => artist.name).join(', ')}</Text>
</View>
<View style={{ flex: 0.7, justifyContent: 'center', alignItems: 'center' }}>
{cards.map((card, index) => (
<View

Loading…
Cancel
Save