Clean redux
continuous-integration/drone/push Build is passing Details

pull/19/head
Emre KARTAL 2 years ago
parent b94cc83dbb
commit 559f299aeb

@ -41,8 +41,8 @@ class UserController implements IController {
try {
const { name, email, password, idSpotify } = req.body;
const token = await this.userService.register(
name,
email,
name.toLowerCase(),
email.toLowerCase(),
password,
idSpotify
);

@ -9,6 +9,7 @@ npm-debug.*
*.mobileprovision
*.orig.*
web-build/
constants/config.ts
# macOS
.DS_Store

@ -17,15 +17,16 @@ export default function FladyComponent(monFlady: Flady) {
const styles = StyleSheet.create({
container: {
width: normalize(152),
height: normalize(152),
borderRadius: 90,
marginHorizontal: normalize(15),
width: normalize(132),
height: normalize(132),
borderRadius: 30,
backgroundColor: 'white',
marginHorizontal: normalize(12),
overflow: 'hidden',
},
image: {
width: normalize(220),
height: normalize(220),
width: normalize(180),
height: normalize(180),
marginLeft: -1
}
})

@ -12,6 +12,4 @@ export default class Artist {
get url(): string {
return this.url;
}
}

@ -13,6 +13,14 @@ export default class Music{
this._trackPreviewUrl = trackPreviewUrl;
}
get id(): string {
return this._id;
}
set id(value: string) {
this._id = value;
}
get title(): string {
return this._title;
}
@ -37,14 +45,6 @@ export default class Music{
this._image = value;
}
get id(): string {
return this._id;
}
set id(value: string) {
this._id = value;
}
get trackPreviewUrl(): string {
return this._trackPreviewUrl;
}

@ -3,19 +3,24 @@ import Music from "./Music";
export class Spot {
private _userId: string;
private _music: Music;
constructor(userId: string, music: Music) {
this._userId = userId;
this._music = music;
}
get userSpotifyId(): string {
return this._userId;
}
set userSpotifyId(value: string) {
this._userId = value;
}
get music(): Music {
return this._music;
}
set music(value: Music) {
this._music = value;
}

@ -6,7 +6,6 @@ export class User {
private _name: string;
public image: string;
//constructors
constructor(idFlad: string, idSpotify: string, email: string, createdAt: Date, name: string, image: string) {
this._name = name;
this._idFlad = idFlad;
@ -31,8 +30,4 @@ export class User {
get name(): string {
return this._name;
}
toString() {
return 'User : ' + this.idFlad + ', ' + this.name + ', ' + this.idSpotify;
}
}

@ -1,14 +1,13 @@
import Music from "../Music";
export default class MusicMapper {
static mapFromSpotifyTrack(jsonMusic: any): Music {
const music = new Music(
jsonMusic.id,
jsonMusic.name,
jsonMusic.artists[0].name,
jsonMusic.album.images[0].url,
jsonMusic.preview_url
static toModel(music: any): Music {
return new Music(
music.id,
music.name,
music.artists[0].name,
music.album.images[0].url,
music.preview_url
);
return music;
}
}

@ -2,11 +2,7 @@ import { User } from "../User";
export class UserMapper {
public static JsonToModel( jsonUser :any ) : User{
return new User(jsonUser.idFlad, jsonUser.idSpotify, jsonUser.email, jsonUser.createdAt, jsonUser.name, jsonUser.imageUrl);
public static toModel(user: any): User {
return new User(user.idFlad, user.idSpotify, user.email, user.createdAt, user.name, user.imageUrl);
}
public static uptade( jsonUser :any ) : User{
return new User(jsonUser.idFlad, jsonUser.idSpotify, jsonUser.email, jsonUser.createdAt, jsonUser.name, jsonUser.imageUrl);
}
}

@ -51,7 +51,7 @@ export default function AuthNavigation() {
{isLogin ? (
<HomeNavigation />
) :
<HomeNavigation />
<StartNavigation />
}
</SafeAreaProvider>
)

@ -32,7 +32,7 @@
"lottie-react-native": "5.1.4",
"react": "18.1.0",
"react-dom": "18.1.0",
"react-native": "0.70.8",
"react-native": "0.70.14",
"react-native-gesture-handler": "~2.8.0",
"react-native-gifted-chat": "^2.0.1",
"react-native-modal": "^13.0.1",

@ -7,6 +7,7 @@ export const getFavoritesMusic = (music: Music[]) => {
payload: music,
};
}
export const addFavoritesMusic = (music: Music) => {
return {
type: favoritesTypes.ADD_FAVORITE_MUSICS,

@ -1,18 +1,19 @@
import { User } from "../../model/User";
import { userTypes } from "../types/userTypes";
export interface Credentials {
export interface LoginCredentials {
email: string,
password: string
}
export interface CredentialsRegister {
export interface RegisterCredentials {
email: string,
password: string,
name: string,
idFlad: string,
idSpotify: string
}
export const setLoginState = (userJson: any) => {
const user = new User(userJson.data.idFlad, userJson.data.idSpotify, userJson.data.email, new Date(), userJson.data.name, userJson.data.image);
return {
@ -27,34 +28,44 @@ export const restoreToken = (token: string) => {
payload: token
};
}
export const userSignUp = (user: User) => {
return {
type: userTypes.LOGIN,
type: userTypes.SIGNUP,
payload: user
};
}
export const UserLogout = () => {
export const userLogout = () => {
return {
type: userTypes.USER_LOGOUT,
};
}
export const userChangeMode = (value: boolean) => {
export const setDarkMode = (value: boolean) => {
return {
type: userTypes.DARK_MODE,
payload: value
};
}
export const setErrorLogin = (value: boolean) => {
return {
type: userTypes.CHANGE_MODE,
type: userTypes.ERROR_LOGIN,
payload: value
};
}
export const ChangeErrorLogin = () => {
export const setErrorSignup = (value: boolean) => {
return {
type: userTypes.CHANGE_ERROR_LOGIN,
type: userTypes.ERROR_SIGNUP,
payload: value
};
}
export const ChangeErrorSignup = () => {
export const setErrorNetwork = (value: boolean) => {
return {
type: userTypes.CHANGE_ERROR_SIGNUP,
type: userTypes.ERROR_NETWORK,
payload: value
};
}

@ -8,7 +8,7 @@ import { spotTypes } from "../types/spotTypes";
const initialState = {
spot: spotsData,
favoriteMusic: [] as Music[],
favoriteMusic: [],
userCurrentMusic: null
}

@ -3,14 +3,13 @@ import { User } from "../../model/User";
import { userTypes } from "../types/userTypes";
const initialState = {
loading: false,
user: User,
userFladToken: "",
userSpotifyToken: null,
error: null,
isLogedIn: false,
failedLogin: false,
failedSignup: false,
errorNetwork: false,
dark: null
}
@ -25,41 +24,39 @@ const userReducer = (state = initialState, action: any) => {
isLogedIn: resp,
};
case userTypes.LOGIN:
AsyncStorage.setItem('dark', JSON.stringify(false)).then(() => { });
return {
...state,
user: action.payload,
failedLogin: false,
isLogedIn: true,
dark: false
isLogedIn: true
};
case userTypes.SIGNUP:
AsyncStorage.setItem('dark', JSON.stringify(false)).then(() => { });
return {
...state,
user: action.payload,
failedSignup: false,
isLogedIn: true,
dark: false
};
case userTypes.USER_LOGOUT:
AsyncStorage.removeItem('dark').then(() => { });
AsyncStorage.removeItem('dark');
return {
...state,
user: null,
isLogedIn: false
isLogedIn: false,
dark: null
}
case userTypes.SAVE_SPOTIFY:
return {
...state,
userSpotifyToken: action.payload,
userSpotifyToken: action.payload
};
case userTypes.CHANGE_ERROR_LOGIN:
return { ...state, failedLogin: true }
case userTypes.CHANGE_ERROR_SIGNUP:
return { ...state, failedSignup: true }
case userTypes.CHANGE_MODE:
case userTypes.ERROR_LOGIN:
return { ...state, failedLogin: action.payload }
case userTypes.ERROR_SIGNUP:
return { ...state, failedSignup: action.payload }
case userTypes.DARK_MODE:
return { ...state, dark: action.payload }
case userTypes.ERROR_NETWORK:
return { ...state, errorNetwork: action.payload }
default:
return state;
}

@ -13,6 +13,7 @@ const reducer = {
}
const store = configureStore({
// @ts-ignore
reducer: reducer,
middleware: (getDefaultMiddleware) => getDefaultMiddleware({
serializableCheck: {

@ -1,69 +1,69 @@
import axios from "axios";
import { API_URL } from "../../assets/constants/config";
import { Credentials, CredentialsRegister, restoreToken, setLoginState, UserLogout, userChangeMode, userSignUp, ChangeErrorLogin, ChangeErrorSignup } from "../actions/userActions";
import configs from "../../constants/config";
import { LoginCredentials, RegisterCredentials, restoreToken, setLoginState, userLogout, setDarkMode, userSignUp, setErrorLogin, setErrorSignup, setErrorNetwork } from "../actions/userActions";
import * as SecureStore from 'expo-secure-store';
import { UserMapper } from "../../model/mapper/UserMapper";
const key = 'userToken';
export const registerUser = (resgisterCredential: CredentialsRegister) => {
export const register = (resgisterCredential: RegisterCredentials) => {
//@ts-ignore
return async dispatch => {
try {
console.log("rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr")
console.log(resgisterCredential);
console.log("rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr")
const config = {
headers: {
'Content-Type': 'application/json',
},
}
const resp = await axios.post(
'https://flad-api-production.up.railway.app/api/users/register',
configs.API_URL + '/users/register',
resgisterCredential,
config
)
if (resp.data.token) {
console.log(resp.data.token);
const token = resp.data.token;
const headers = {
'Authorization': 'Bearer ' + token
};
const user = await axios.get(
"https://flad-api-production.up.railway.app/api/users",
configs.API_URL + 'api/users',
{ headers }
)
dispatch(userSignUp(UserMapper.JsonToModel(user.data)));
dispatch(userSignUp(UserMapper.toModel(user.data)));
} else {
console.log('Login Failed', 'Username or Password is incorrect');
dispatch(setErrorSignup(true))
}
} catch (error) {
console.log('Login Failed'+ error.message + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
dispatch(ChangeErrorSignup())
if (axios.isAxiosError(error)) {
dispatch(setErrorNetwork(true));
} else {
dispatch(setErrorLogin(true));
}
}
}
}
export const userLogin = (loginCredential: Credentials) => {
export const login = (loginCredential: LoginCredentials) => {
//@ts-ignore
return async dispatch => {
try {
console.log(loginCredential);
const config = {
headers: {
'Content-Type': 'application/json',
},
}
console.log(configs.API_URL + '/users/login')
console.log(loginCredential)
console.log(config)
const resp = await axios.post(
"https://flad-api-production.up.railway.app/api/users/login",
configs.API_URL + '/users/login',
loginCredential,
config
)
if (resp.data.token) {
const token = resp.data.token;
await SecureStore.setItemAsync(key, token);
@ -72,18 +72,21 @@ export const userLogin = (loginCredential: Credentials) => {
};
const user = await axios.get(
"https://flad-api-production.up.railway.app/api/users",
configs.API_URL + '/users',
{ headers }
)
console.log(user.data);
dispatch(setLoginState(user.data));
} else {
console.log('Login Failed', 'Username or Password is incorrect');
dispatch(setErrorLogin(true));
}
} catch (error) {
dispatch(ChangeErrorLogin())
if (axios.isAxiosError(error)) {
console.log("axios : " + error.message);
dispatch(setErrorNetwork(true));
} else {
dispatch(setErrorLogin(true));
}
}
}
}
@ -107,29 +110,29 @@ export const getRefreshToken = () => {
}
export const DeleteToken = () => {
export const deleteToken = () => {
//@ts-ignore
return async dispatch => {
try {
await SecureStore.deleteItemAsync(key);
dispatch(UserLogout());
dispatch(userLogout());
} catch (e) {
console.log('Error deleting token', e);
}
}
}
export const ChangeMode = (value: boolean) => {
export const darkMode = (value: boolean) => {
//@ts-ignore
return async dispatch => {
dispatch(userChangeMode(value));
dispatch(setDarkMode(value));
}
}
export const ChangeImageUserCurrent = (value: ImagePicker) => {
export const imageUserCurrent = (value: any) => {
//@ts-ignore
return async dispatch => {
//@ts-ignore
dispatch(userChangeImage(value));
dispatch(setImageUserCurrent(value));
}
}

@ -1,12 +1,12 @@
export const userTypes = {
RESTORE_TOKEN: "RESTORE_TOKEN",
LOGIN: 'LOGIN',
SIGNUP: 'SIGNUP',
USER_LOGOUT: 'USER_LOGOUT',
SAVE_SPOTIFY: 'SAVE_SPOTIFY',
UPDATE_USER: 'UPDATE_USER',
UPDATE_PROFILE_PICTURE: 'UPDATE_PROFILE_PICTURE',
USER_LOGOUT: 'USER_LOGOUT',
RESTORE_TOKEN: "RESTORE_TOKEN",
CHANGE_MODE: "CHANGE_MODE",
CHANGE_ERROR_LOGIN: "CHANGE_ERROR_LOGIN",
CHANGE_ERROR_SIGNUP: "CHANGE_ERROR_SIGNUP"
ERROR_LOGIN: "ERROR_LOGIN",
ERROR_SIGNUP: "ERROR_SIGNUP",
DARK_MODE: "DARK_MODE",
ERROR_NETWORK: "ERROR_NETWORK"
}

@ -1,5 +1,5 @@
import React from 'react';
import { Image, StyleSheet, Text, View, FlatList, TouchableOpacity, TouchableHighlight, SafeAreaView } from 'react-native';
import { StyleSheet, Text, View, FlatList, TouchableHighlight, SafeAreaView } from 'react-native';
import CardMusic from '../components/CardMusicComponent';
import normalize from '../components/Normalize';
import Music from '../model/Music'

@ -1,11 +1,12 @@
import React, { useState } from 'react';
import { View, Image, StyleSheet, Text, ImageBackground, TextInput, TouchableWithoutFeedback, Keyboard, TouchableOpacity } from 'react-native';
import React, { useEffect, useState } from 'react';
import { Alert, View, Image, StyleSheet, Text, ImageBackground, TextInput, TouchableWithoutFeedback, Keyboard, TouchableOpacity } from 'react-native';
import { setErrorNetwork } from "../redux/actions/userActions";
import { useNavigation } from "@react-navigation/native";
import normalize from '../components/Normalize';
import { userLogin } from '../redux/thunk/authThunk';
import { login } from '../redux/thunk/authThunk';
import { useDispatch, useSelector } from 'react-redux';
import { Audio } from 'expo-av';
import { Credentials } from '../redux/actions/userActions';
import { LoginCredentials } from '../redux/actions/userActions';
// @ts-ignore
const DismissKeyboard = ({ children }) => (
@ -20,11 +21,13 @@ export default function LoginScreen() {
const navigation = useNavigation();
// @ts-ignore
const failedLogin = useSelector(state => state.userReducer.failedLogin);
// @ts-ignore
const networkError = useSelector(state => state.userReducer.errorNetwork);
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
async function playSound() {
console.log('Loading Sound');
const { sound } = await Audio.Sound.createAsync(
require('../assets/sounds/click.mp3')
);
@ -34,15 +37,33 @@ export default function LoginScreen() {
const dispatch = useDispatch();
const submitForm = () => {
const credentials: Credentials = {
email: username,
password: password
const credentials: LoginCredentials = {
email: username.toLowerCase(),
password: password.toLowerCase()
};
//@ts-ignore
dispatch(userLogin(credentials))
dispatch(login(credentials))
playSound()
}
useEffect(() => {
if (networkError) {
Alert.alert(
'Erreur réseau',
'Une erreur réseau s\'est produite. Veuillez vérifier votre connexion internet et réessayer.',
[
{
text: 'OK',
onPress: () => {
dispatch(setErrorNetwork(false));
},
},
],
{ cancelable: false }
);
}
}, [networkError, dispatch]);
const toggleRememberMe = () => {
setRememberMe(!rememberMe);
}

@ -4,14 +4,13 @@ import { useNavigation } from "@react-navigation/native";
import normalize from '../components/Normalize';
import * as SecureStore from 'expo-secure-store';
import * as AuthSession from 'expo-auth-session';
import { makeRedirectUri, useAuthRequest } from 'expo-auth-session';
import { registerUser } from '../redux/thunk/authThunk';
import { register } from '../redux/thunk/authThunk';
import { useDispatch, useSelector } from 'react-redux';
import { Audio } from 'expo-av';
import { CredentialsRegister } from '../redux/actions/userActions';
import { RegisterCredentials } from '../redux/actions/userActions';
import * as WebBrowser from 'expo-web-browser';
import { spotArray2 } from '../data/data';
import { setSpotList } from '../redux/actions/spotActions';
import { spotsData } from '../data/data';
// @ts-ignore
const DismissKeyboard = ({ children }) => (
@ -51,11 +50,11 @@ export default function RegisterScreen() {
const dispatch = useDispatch();
function addMockSpots() {
dispatch(setSpotList(spotArray2))
dispatch(setSpotList(spotsData))
}
const submitForm = () => {
const credentials: CredentialsRegister = {
const credentials: RegisterCredentials = {
email: email,
password: password,
idSpotify: spotifyToken,
@ -64,7 +63,7 @@ export default function RegisterScreen() {
};
//@ts-ignore
dispatch(registerUser(credentials))
dispatch(register(credentials))
addMockSpots()
playSound()
}

@ -1,123 +0,0 @@
import { View, Text, StyleSheet, Button } from 'react-native'
import React from 'react'
import * as AuthSession from 'expo-auth-session';
import * as WebBrowser from 'expo-web-browser';
import { makeRedirectUri, useAuthRequest } from 'expo-auth-session';
import { Buffer } from 'buffer';
import * as SecureStore from 'expo-secure-store';
WebBrowser.maybeCompleteAuthSession()
const discovery = {
authorizationEndpoint: 'https://accounts.spotify.com/authorize',
tokenEndpoint: 'https://accounts.spotify.com/api/token',
};
export default function Login() {
const [request] = useAuthRequest(
{
responseType: AuthSession.ResponseType.Token,
clientId: '1f1e34e4b6ba48b388469dba80202b10',
scopes: ['user-read-private', 'user-read-email', 'user-read-playback-state', 'user-read-currently-playing', 'user-read-recently-played', 'playlist-modify-public', 'ugc-image-upload', 'user-modify-playback-state'],
usePKCE: false,
redirectUri: makeRedirectUri({
scheme: 'https://auth.expo.io/@anonymous/FLAD-7eafd441-fd6b-4fb6-924c-ec2b0ed5ce6d',
useProxy: true
})
},
discovery
);
const scopesArr = ['user-read-private', 'user-read-email', 'user-read-playback-state', 'user-read-currently-playing', 'user-read-recently-played', 'playlist-modify-public', 'ugc-image-upload', 'user-modify-playback-state'];
const scopes = scopesArr.join(' ');
const getAuthorizationCode = async () => {
try {
const redirectUrl = "https://auth.expo.io/@anonymous/FLAD-7eafd441-fd6b-4fb6-924c-ec2b0ed5ce6d"
const result = await AuthSession.startAsync({
authUrl:
'https://accounts.spotify.com/authorize' +
'?response_type=code' +
'&client_id=' +
"1f1e34e4b6ba48b388469dba80202b10" +
(scopes ? '&scope=' + encodeURIComponent(scopes) : '') +
'&redirect_uri=' +
encodeURIComponent(redirectUrl),
})
return result.params.code;
} catch (err) {
console.error(err)
}
}
const getTokens = async () => {
try {
const authorizationCode = await getAuthorizationCode()
await fetch('https://accounts.spotify.com/api/token', {
method: 'POST',
headers: {
Authorization: 'Basic ' + (Buffer.from('1f1e34e4b6ba48b388469dba80202b10' + ':' + '779371c6d4994a68b8dd6e84b0873c82').toString('base64')),
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `grant_type=authorization_code&code=${authorizationCode}&redirect_uri=https://auth.expo.io/@anonymous/FLAD-7eafd441-fd6b-4fb6-924c-ec2b0ed5ce6d`,
});
} catch (err) {
console.error(err)
}
}
return (
<View style={styles.centeredView}>
<Text style={styles.textStyle}>Hello flad test logIn</Text>
<Button disabled={!request} title="Login"
onPress={() => {
getTokens()
}}
/>
</View>
);
};
const styles = StyleSheet.create({
centeredView: {
justifyContent: 'center',
alignItems: 'center',
marginTop: 22,
},
modalView: {
margin: 20,
backgroundColor: 'white',
borderRadius: 20,
padding: 35,
alignItems: 'center',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 4,
},
header: {
alignItems: 'flex-end',
justifyContent: 'center',
},
button: {
borderRadius: 20,
padding: 10,
elevation: 2,
},
buttonOpen: {
backgroundColor: '#F194FF',
},
textStyle: {
color: 'white',
fontWeight: 'bold',
textAlign: 'center',
},
close: {
alignSelf: 'flex-end',
backgroundColor: 'red',
justifyContent: 'center'
}
})

@ -2,6 +2,7 @@ import axios from "axios";
import MusicMapper from "../../model/mapper/MusicMapper";
import Music from "../../model/Music";
import { FetchOptions, RequestHandler } from "./spotifyRequestHandler/utils";
export class MusicMinimal {
public id: string;
public title: string;
@ -15,7 +16,7 @@ export class MusicMinimal {
}
export default class SpotifyService implements IspotifyService {
private readonly API_URL = "https://flad-api-production.up.railway.app/api/";
private readonly API_URL = API_URL;
private spotifyRequestHandler = new RequestHandler();
public token: string;

@ -1,5 +0,0 @@
export class UserService {
}
Loading…
Cancel
Save