Mongo database almost done

pull/7/head
David D'ALMEIDA 2 years ago
parent b11b3b01e4
commit 464933ef68

@ -11,9 +11,11 @@
"author": "",
"license": "ISC",
"devDependencies": {
"@types/bcrypt": "^5.0.0",
"@types/cors": "^2.8.13",
"@types/debug": "^4.1.7",
"@types/express": "^4.17.16",
"@types/jsonwebtoken": "^9.0.1",
"@types/morgan": "^1.9.4",
"nodemon": "^2.0.20",
"ts-node": "^10.9.1",
@ -24,8 +26,11 @@
"@types/mongoose": "^5.11.97",
"@types/request": "^2.48.8",
"axios": "^1.2.6",
"bcrypt": "^5.1.0",
"cors": "^2.8.5",
"express-winston": "^4.2.0",
"joi": "^17.8.1",
"jsonwebtoken": "^9.0.0",
"mongodb": "^5.0.0",
"mongoose": "^6.9.0",
"morgan": "^1.10.0",

@ -6,6 +6,7 @@ import cors from 'cors';
import Controller from './controller/Icontroller';
// import ErrorMiddleware from './middleware/error.middleware';
import bodyParser from 'body-parser';
import mongoose from 'mongoose';
// to secure
// import helmet from 'helmet';
@ -24,7 +25,7 @@ class App {
this.port = port;
this.dataBase = null;
// this.initialiseDatabase();
this.initialiseDatabase();
this.initialiseMiddleware();
this.initialiseControllers(controllers);
@ -61,7 +62,14 @@ class App {
console.log(`⚡️[server] : App listening on the port ${this.port}`);
});
}
private initialiseDatabase(): void {
const { MONGO_USER, MONGO_PASSWORD, MONGO_PATH } = process.env;
const uri = "mongodb+srv://fladDevDb:ZslYlNRWIOUU7i6o@fladcluster.b29tytu.mongodb.net/?retryWrites=true&w=majority"
mongoose.connect(uri)
.then(() => console.log("Connect to MongoDB database successfully"))
.catch(err => console.log("Error connecting : "+ err ));
}
}

@ -23,6 +23,8 @@ class SpotifyController implements Controller {
this.router.get(`${this.path}/callback`,this.getAccessToken);
// this.router.post(`${this.path}/refresh`,this.getRefreshToken);
this.router.get(`${this.path}/play/:musicId`, this.getMusic);
this.router.get(`${this.path}/spot`, this.getSpot);
}
// need to put in ENvironement file
@ -134,85 +136,49 @@ class SpotifyController implements Controller {
}
}
// };
public getMusic(){
return null;
}
// private spotifyRequest = (params : AuthReqBody) => {
// return new Promise<any>(() => {
// console.log("============ on est laaaa sa mer");
// var code = req.query.code || null;
// var state = req.query.state || null;
public getSpot = async (
req: Request,
res: Response,
next: NextFunction
): Promise<Response | void> => {
const spots = [
{
name: "blue",
sourceUrl: "https://cdns-images.dzcdn.net/images/artist/399e7e760d8fedf3cc2891e9c0c41658/200x200-000000-80-0-0.jpg",
index: 3
},
{
name: "strange history",
sourceUrl: "https://images.genius.com/339dfe2a7c0adf9a5d08febf29a845f4.1000x1000x1.jpg",
index: 7
},
{
name: "oboy album",
sourceUrl: "https://i.pinimg.com/originals/ad/cc/d5/adccd58a0d0ff516a6114703cd05810e.jpg",
index: 1
}
];
try {
res.send(spots);
} catch (error) {
console.log('heuuuuuuuuuuuuuuuuuuuuubizzzaaarrreeee');
console.log(error);
next(new HttpException(400, 'On peut pas avoir darray mec'));
} }
// axios.post(this.API_URL, {
// form: params,
// headers: {
// "Authorization": "Basic " + new Buffer(this.CLIENT_ID + ":" + this.CLIENT_SECRET).toString('base64')
// },
// json: true
// });
// }).then(resp => {
// if (resp.statusCode != 200) {
// return Promise.reject({
// statusCode: resp.statusCode,
// body: resp.body
// });
// }
// return Promise.resolve(resp.body);
// })
// .catch(err => {
// return Promise.reject({
// statusCode: 500,
// body: err.stringify({})
// });
// });
// };
private getAccessToken = async (
req: Request,
res: Response,
next: NextFunction
): Promise<Response | void> => {
// console.log("heheh");
// try {
// var code = req.query.code;
// var state = req.query.state;
// console.log("================================================================================================================================");
// console.log(req);
// console.log("================================================================================================================================");
// if (state === null) {
// next(new HttpException(400, 'Cannot create twerk'));
// } else {
// const resp : any = await axios.post('https://accounts.spotify.com/api/token',{
// form: {
// code: code,
// redirect_uri: this.CALLBACK_URL,
// // code_verifier : this.ENCRYPTION_SECRET.stringCrypt,
// grant_type: 'authorization_code'
// },
// headers: {
// 'Authorization': 'Basic ' + (new Buffer(this.CLIENT_ID + ':' + this.CLIENT_SECRET).toString('base64')),
// },json: true}
// );
// if (resp.statusCode != 200) {
// console.log(resp.statusCode, resp.body);
// }
// else{
// console.log("error");
// console.log(resp.statusCode, resp.body);
// }
// }
// // });
// } catch (error) {
// console.log(error);
// next(new HttpException(400, 'Cannot create spot'));
// }
var code = req.query.code;
var state = req.query.state || null;
@ -249,39 +215,9 @@ class SpotifyController implements Controller {
}
// axios({
// method: 'post',
// url: 'https://accounts.spotify.com/api/token',
// data: {
// firstName: 'Fred',
// lastName: 'Flintstone'
// },
// headers: {
// 'Authorization': 'Basic ' + ( Buffer.from(this.CLIENT_ID + ':' + this.CLIENT_SECRET).toString('base64')),
// 'Content-Type' : 'application/x-www-form-urlencoded'
// },
// });
// request.post(authOptions, function(error, response, body) {
// if (!error && response.statusCode === 200) {
// var access_token = body.access_token;
// console.log(access_token);
// res.redirect(200, '/')
// }
// console.log(error);
// });
};
private encrypt(text :any){
return CryptoJS.AES.encrypt(text, this.ENCRYPTION_SECRET.stringCrypt).toString();
};
private decrypt(text: any) {
console.log("errer");
var bytes = CryptoJS.AES.decrypt(text, this.ENCRYPTION_SECRET.stringCrypt);
return bytes.toString(CryptoJS.enc.Utf8);
};
}
export default SpotifyController;

@ -1,11 +1,15 @@
import { Router, Request, Response, NextFunction, RequestHandler } from 'express';
import Controller from '../Icontroller';
import HttpException from '../../middleware/exeption/httpExeption';
// import LocationService from '../../service/LocationService';
import IUser from '../../database/schema/User/UserInterface';
import UserService from '../../service/UserService';
import validator from '../../database/schema/User/UserValidation'
import validationMiddleware from '../../middleware/validation/ValidatorMiddleware';
import authenticator from '../../middleware/authMiddleware'
import LocationService from '../../service/LocationService';
class TaskController implements Controller {
public path = '/task';
class UserController implements Controller {
public path = '/users';
public router = Router();
private userService = new UserService();
private locationService = new LocationService();
@ -15,131 +19,193 @@ class TaskController implements Controller {
}
private initialiseRoutes(): void {
//create
this.router.post(`${this.path}`,this.createUser);
// // get One
this.router.get (`${this.path}/:userId`, this.getUserById);
// // get All
this.router.get (`${this.path}`, this.getAllUsers);
this.router.post(
`${this.path}/register`,
validationMiddleware(validator.register),
this.register
);
this.router.post(
`${this.path}/login`,
validationMiddleware(validator.login),
this.login
);
this.router.get(`${this.path}`, authenticator, this.getUser);
this.router.get(`${this.path}/nextTo`, authenticator, this.getUserNext);
//update One
this.router.put (`${this.path}/:userId`, this.updateUser);
//Delete One
this.router.delete (`${this.path}/:userId`, this.deleteUser);
// //create
// this.router.post(`${this.path}`,this.createUser);
// // // get One
// this.router.get (`${this.path}/:userId`, this.getUserById);
// // // get All
// this.router.get (`${this.path}`, this.getAllUsers);
// //update One
// this.router.put (`${this.path}/:userId`, this.updateUser);
// //Delete One
// this.router.delete (`${this.path}/:userId`, this.deleteUser);
}
private createUser = async (
req: Request,
res: Response,
next: NextFunction
): Promise<Response | void> => {
try {
// private createUser = async (
// req: Request,
// res: Response,
// next: NextFunction
// ): Promise<Response | void> => {
// try {
console.log(req.body);
const reqBody:CreateTaskReqBody = Object.assign({}, req.body);
checkIfIsValidCreateTaskReqBody(reqBody);
await this.userService.createUserById(reqBody.fin
);
// console.log(req.body);
// const reqBody:CreateTaskReqBody = Object.assign({}, req.body);
// checkIfIsValidCreateTaskReqBody(reqBody);
// await this.userService.createUserById(reqBody.fin
// );
res.status(200).send({ status: "Success", msg: "Success add" });
// res.status(200).send({ status: "Success", msg: "Success add" });
} catch (error) {
next(new HttpException(400, 'Cannot create post'));
}
};
private readonly getUserById: RequestHandler = async (
req: Request,
res: Response,
next: NextFunction
): Promise<Response | void> => {
try {
const id = req.params.taskId;
const userId = req.params.userId;
// } catch (error) {
// next(new HttpException(400, 'Cannot create post'));
// }
// };
// private readonly getUserById: RequestHandler = async (
// req: Request,
// res: Response,
// next: NextFunction
// ): Promise<Response | void> => {
// try {
// const id = req.params.taskId;
// const userId = req.params.userId;
const data = await this.userService.getUserById(id, userId);
res.status(201).send(data);
// const data = await this.userService.getUserById(id, userId);
// res.status(201).send(data);
}
catch(error){
next(new HttpException(400, 'Cannot create post'));
}
// }
// catch(error){
// next(new HttpException(400, 'Cannot create post'));
// }
}
private readonly getAllUsers: RequestHandler = async (
// }
// private readonly getAllUsers: RequestHandler = async (
// req: Request,
// res: Response,
// next: NextFunction
// ): Promise<Response | void> => {
// try {
// const userId = req.params.userId;
// const tasks = await this.userService.getUsers(userId);
// const responseList = tasks.map(task => new TaskResumedRes(task));
// res.status(201).send(responseList);
// }
// catch(error){
// next(new HttpException(400, 'Cannot get user task'));
// }
// }
// private deleteUser = async (
// req: Request,
// res: Response,
// next: NextFunction
// ): Promise<Response | void> => {
// try {
// const id = req.params.taskId;
// const userId = req.params.userId;
// await this.userService.DeleteUser(id, userId);
// return res.status(200).send({ status: "Success", msg: "Data Removed" });
// } catch (error) {
// next(new HttpException(400, 'Cannot create post'));
// }
// };
// private updateUser = async (
// req: Request,
// res: Response,
// next: NextFunction
// ): Promise<Response | void> => {
// try {
// const taskId = req.params.taskId;
// const userId = req.params.userId;
// const reqBody:CreateTaskReqBody = Object.assign({}, req.body);
// const updatedTask = await this.userService.UpdateTask(
// // req.auth!.uid,
// taskId,
// userId,
// // firebase.auth().currentUser.getIdToken()
// reqBody.nom,
// reqBody.description,
// reqBody.logo,
// reqBody.duration,
// reqBody.done,
// // reqBody.tags,
// reqBody.repepat,
// reqBody.deb,
// reqBody.fin
// );
// // res.send('Success add');
// // res.status(201).json({ task });
// res.status(204).send(`Update a new contact: ${updatedTask}`);
// } catch (error) {
// console.log(error);
// next(new HttpException(403, 'Cannot create post'));
// }
// };
private register = async (
req: Request,
res: Response,
next: NextFunction
): Promise<Response | void> => {
try {
const userId = req.params.userId;
const tasks = await this.userService.getUsers(userId);
const responseList = tasks.map(task => new TaskResumedRes(task));
res.status(201).send(responseList);
// the FladId should be created by the Userservice
const { name, email, password,idFlad, idSpotify } = req.body;
const token = await this.userService.register(
name,
email,
password,
idFlad,
idSpotify
);
res.status(201).json({ token });
} catch (error : any) {
next(new HttpException(400, error.message));
}
catch(error){
next(new HttpException(400, 'Cannot get user task'));
}
}
private deleteUser = async (
};
private login = async (
req: Request,
res: Response,
next: NextFunction
): Promise<Response | void> => {
try {
const id = req.params.taskId;
const userId = req.params.userId;
await this.userService.DeleteUser(id, userId);
return res.status(200).send({ status: "Success", msg: "Data Removed" });
} catch (error) {
next(new HttpException(400, 'Cannot create post'));
const { email, password } = req.body;
const token = await this.userService.login(email, password);
res.status(200).json({ token });
} catch (error : any) {
next(new HttpException(400, error.message));
}
};
private updateUser = async (
private getUser = (
req: Request,
res: Response,
next: NextFunction
): Promise<Response | void> => {
try {
const taskId = req.params.taskId;
const userId = req.params.userId;
const reqBody:CreateTaskReqBody = Object.assign({}, req.body);
const updatedTask = await this.userService.UpdateTask(
// req.auth!.uid,
taskId,
userId,
// firebase.auth().currentUser.getIdToken()
reqBody.nom,
reqBody.description,
reqBody.logo,
reqBody.duration,
reqBody.done,
// reqBody.tags,
reqBody.repepat,
reqBody.deb,
reqBody.fin
);
// res.send('Success add');
// res.status(201).json({ task });
res.status(204).send(`Update a new contact: ${updatedTask}`);
} catch (error) {
console.log(error);
next(new HttpException(403, 'Cannot create post'));
): Response | void => {
if (!req.user) {
return next(new HttpException(404, 'No logged in user'));
}
res.status(200).send({ data: req.user });
};
private getUserNext: RequestHandler = async (
private getUserNext = async (
req: Request,
res: Response,
next: NextFunction
@ -152,18 +218,29 @@ class TaskController implements Controller {
console.log('Impossible de convertir la chaîne en nombre');
}
//}
const userId = req.body.userId;
const userId = req.user.idFlad;
const data = await this.locationService.getNearUser(userId,latitude,longitude);
console.log(data);
res.status(201).send(data);
}
catch(error){
next(new HttpException(400, 'Cannot create post'));
catch(error : any){
next(new HttpException(400, 'Cannot create get netUser'));
}
}
}
export default TaskController;
export default UserController;
declare global {
namespace Express {
export interface Request {
user: IUser;
}
}
}

@ -1,3 +1,4 @@
const uri = "mongodb+srv://fladDevDb:ZslYlNRWIOUU7i6o@fladcluster.b29tytu.mongodb.net/?retryWrites=true&w=majority"
export default db = new MongoClient(uri);
// export default db = new MongoClient(uri);

@ -0,0 +1,36 @@
import { Schema, model } from 'mongoose';
const locationSchema = new Schema(
{
idFlad: {
type: String,
required: true,
unique: true,
},
latitude: {
type: Number,
required: true,
},
longitude: {
type: Number,
required: true,
},
},
{ timestamps: true }
);
// fladDevDb
// ZslYlNRWIOUU7i6o
export default model<ILocation>('Location', locationSchema);
export interface ILocation extends Document {
idFlad: string;
latitude : number;
longitude: number;
}

@ -1,6 +1,8 @@
const notificationSchema = new mongoose.Schema({
import { Schema, model } from 'mongoose';
const notificationSchema = new Schema({
type: {type: String, required: true},
content: {type: String, required: true}
});
export default {Annonce: mongoose.model("nofitication", notificationSchema)}
export default {Notification: model("nofitication", notificationSchema)}

@ -0,0 +1,8 @@
import { Schema } from 'mongoose';
interface IToken extends Object {
id: Schema.Types.ObjectId;
expiresIn: number;
}
export default IToken;

@ -0,0 +1,11 @@
import { Document } from 'mongoose';
export default interface IUser extends Document {
email: string;
name: string;
password: string;
idFlad : string;
idSpotify : string;
isValidPassword(password: string): Promise<Error | boolean>;
}

@ -0,0 +1,79 @@
// maye this file should me the UserModel like we had in php cause it's here we verrify the password
import IUser from "./UserInterface";
import { Schema, model } from 'mongoose';
import bcrypt from 'bcrypt';
// const userSchema: Schema = new Schema<IUser>({
// pseudo: {type: String, index: { unique: true }},
// email: {type: String},
// idDafl: {type: String, index: { unique: true }},
// idSpotify: {type: String},
// password: {type: String},
// prenom: {type: String, default: ""},
// description: {type: String, default: ""},
// nom: {type: String, default: ""},
// ville: {type: String, default: ""},
// profilPic: {type: String},
// noteList: [],
// notifications: [],
// friends: {type: [String] },
// favoris: [],
// conversations: {type: [String] }
// });
const userSchema = new Schema(
{
idFlad: {
type: String,
required: true,
unique: true,
},
idSpotify: {
type: String,
required: true,
unique: true,
},
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
// this mean that we identify user by email
unique: true,
// delete the whitespace
trim: true,
},
password: {
type: String,
},
},
{ timestamps: true }
);
// this means that we hash the user password before saving it to the database
userSchema.pre<IUser>('save', async function (next) {
if (!this.isModified('password')) {
//just had that to be sure that the api still going
return next();
}
const hash = await bcrypt.hash(this.password, 8);
this.password = hash;
next();
});
userSchema.methods.isValidPassword = async function (
password: string
): Promise< boolean | Error> {
return await bcrypt.compare(password, this.password);
};
// fladDevDb
// ZslYlNRWIOUU7i6o
export default model<IUser>('User', userSchema);
// export const User: Model<IUser> = model('User', userSchema);

@ -0,0 +1,18 @@
import Joi from 'joi';
const register = Joi.object({
name: Joi.string().max(30).required(),
email: Joi.string().email().required(),
password: Joi.string().min(6).required(),
// can add an field like confimPassword and cheked that the password is equal to the confirmPassword
});
const login = Joi.object({
email: Joi.string().email().required(),
password: Joi.string().required(),
});
export default { register, login };

@ -1,21 +0,0 @@
const userSchema: Schema = new mongoose.Schema<IUser>({
pseudo: {type: String, index: { unique: true }},
email: {type: String},
idDafl: {type: String, index: { unique: true }},
idSpotify: {type: String},
password: {type: String},
prenom: {type: String, default: ""},
description: {type: String, default: ""},
nom: {type: String, default: ""},
ville: {type: String, default: ""},
profilPic: {type: String},
noteList: [],
notifications: [],
friends: {type: [String] },
favoris: [],
conversations: {type: [String] }
});
// fladDevDb
// ZslYlNRWIOUU7i6o
export const User: Model<IUser> = model('User', userSchema);

@ -0,0 +1,45 @@
import { Request, Response, NextFunction } from 'express';
import jwt from 'jsonwebtoken';
import IToken from '../database/schema/Token/IToken';
import UserSchema from '../database/schema/User/UserSchema';
import token from '../model/token';
import HttpException from './exeption/httpExeption';
async function authenticatedMiddleware(
req: Request,
res: Response,
next: NextFunction
): Promise<Response | void> {
const bearer = req.headers.authorization;
if (!bearer || !bearer.startsWith('Bearer ')) {
return next(new HttpException(401, 'Unauthorised'));
}
const accessToken = bearer.split('Bearer ')[1].trim();
try {
const payload: IToken | jwt.JsonWebTokenError = await token.verifyToken(
accessToken
);
if (payload instanceof jwt.JsonWebTokenError) {
return next(new HttpException(401, 'Unauthorised'));
}
const user = await UserSchema.findById(payload.id)
.select('-password')
.exec();
if (!user) {
return next(new HttpException(401, 'Unauthorised'));
}
req.user = user;
return next();
} catch (error) {
return next(new HttpException(401, 'Unauthorised'));
}
}
export default authenticatedMiddleware;

@ -0,0 +1,33 @@
import { Request, Response, NextFunction, RequestHandler } from 'express';
import Joi from 'joi';
function validationMiddleware(schema: Joi.Schema): RequestHandler {
return async (
req: Request,
res: Response,
next: NextFunction
): Promise<void> => {
const validationOptions = {
abortEarly: false,
allowUnknown: true,
stripUnknown: true,
};
try {
const value = await schema.validateAsync(
req.body,
validationOptions
);
req.body = value;
next();
} catch (e: any) {
const errors: string[] = [];
e.details.forEach((error: Joi.ValidationErrorItem) => {
errors.push(error.message);
});
res.status(400).send({ errors: errors });
}
};
}
export default validationMiddleware;

@ -0,0 +1,27 @@
import jwt from 'jsonwebtoken';
import IUser from '../database/schema/User/UserInterface';
import IToken from '../database/schema/Token/IToken';
export const createToken = (user: IUser): string => {
return jwt.sign({ id: user._id }, "foo" as jwt.Secret, {
expiresIn: '100d',
});
};
export const verifyToken = async (
token: string
): Promise<jwt.VerifyErrors | IToken> => {
return new Promise((resolve, reject) => {
jwt.verify(
token,
"foo" as jwt.Secret,
(err, payload) => {
if (err) return reject(err);
resolve(payload as IToken);
}
);
});
};
export default { createToken, verifyToken };

@ -1,9 +1,10 @@
import App from "./app";
import SpotifyController from "./controller/spotify-controller/spotifyCtrl";
import PingController from "./controller/TestCtrl";
import UserController from "./controller/user-controller/userCtrl";
const app = new App(
[new PingController(), new SpotifyController()],
[new PingController(), new SpotifyController(), new UserController()],
Number(8080)
// Number(process.env.PORT)

@ -1,45 +1,48 @@
// import db from '../database';
import { Place, PlacePosition, Position, UserLocation } from '../model/locationModel';
import axios from 'axios';
import LocationSchema from "../database/schema/LocationSchema";
class LocationService {
private API_KEY : string = "AIzaSyBFCEAtmhZ8jvw84UTQvX3Aqpr66GVqB_A";
public async getNearUser(uuid : string, latitude : number, longitude : number)
private locationCollection = LocationSchema;
// private API_KEY : string = "AIzaSyBFCEAtmhZ8jvw84UTQvX3Aqpr66GVqB_A";
public async getNearUser(idFlad : string, latitude : number, longitude : number)
{
const UserCollectionref = db.collection('UserPosition');
db.collection('UserPosition').doc(uuid).set({uuid : uuid, latitude : latitude, longitude : longitude});
// const newPosition = {
// name: 'Los Angeles',
// state: 'CA',
// country: 'USA'
// };
const snapshot = await UserCollectionref.where("uuid", "!=", uuid).get();
if (snapshot.empty) {
console.log('No matching documents.');
return;
}
await this.locationCollection.findOneAndUpdate(
{ idFlad },
{ idFlad, latitude, longitude },
{ upsert: true }
);
const snapshot = await this.locationCollection.find({ idFlad: { $ne: idFlad } });
if (snapshot.length === 0) {
console.log('No matching documents.');
return;
}
let dbUsersList:UserLocation[] = [];
snapshot.forEach(doc => {
dbUsersList.push(new UserLocation(doc.data().uuid,doc.data().latitude,doc.data().longitude));
console.log(doc.id, '=>', doc.data());
dbUsersList.push(new UserLocation(doc.idFlad,doc.latitude,doc.longitude));
console.log(doc.idFlad, '=>', doc);
});
let listUser: string[] = []; //Set the listUser to an empty list
// missing the curent music
let listUser: string[] = [];
dbUsersList.forEach(user => {
console.log(user);
const dist = this.distanceBetween(latitude , longitude , user.latitude, user.longitude); //With the function meters, determinate the distance between the current user and the user who is in the actual row
const dist = this.distanceBetween(latitude , longitude , user.latitude, user.longitude);
console.log(user.uuid,dist);
if (dist <= 5) { //If the user in the actual row is less than 100 meters away of the current user
if (dist <= 100) {
listUser.push(user.uuid); //Add the username and the ID of the song that user who is in the actual row is listening
listUser.push(user.uuid);
}
});
});
return listUser; //Return an array
// $listUser[] = ['user' => $userID, 'music' => $idMusic]; //Add the username and the ID of the song that user who is in the actual row is listening
return listUser;
// $listUser[] = {userID,idMusic};
}

@ -0,0 +1,63 @@
import UserSchema from "../database/schema/User/UserSchema";
import token from "../model/token";
class UserService {
private user = UserSchema;
/**
* Register a new user
*/
public async register(
name: string,
email: string,
password: string,
idFlad : string,
idSpotify : string
): Promise<string | Error> {
try {
const user = await this.user.create({
name,
email,
password,
idFlad,
idSpotify
});
const accessToken = token.createToken(user);
return accessToken;
} catch (error : any) {
throw new Error(error.message);
}
}
/**
* Attempt to login a user
*/
public async login(
email: string,
password: string
): Promise<string | Error> {
try {
// should maybe creat a method base on id and other information for better security
// need to view with Emre
const user = await this.user.findOne({ email });
// const user = await this.user.findById(idFlad);
if (!user) {
throw new Error('Unable to find user with that email address');
}
if (await user.isValidPassword(password)) {
return token.createToken(user);
} else {
throw new Error('Wrong credentials given');
}
} catch (error) {
throw new Error('Unable to create user');
}
}
}
export default UserService;

@ -8,20 +8,50 @@ import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { Animated, Dimensions, ImageBackground, StyleSheet, Text, View } from 'react-native';
import Card from './components/Card';
import Login from './pages/login';
import Spot from './pages/spot';
// import Login from './screens/login';
import Spot from './screens/spot';
import StackNavigation from './navigation/Navigation';
export default function App() {
const Stack = createBottomTabNavigator();
const {width : wWidht} = Dimensions.get("window");
return (
<Navigation/>
<StackNavigation/>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
card: {
borderRadius : 8,
shadowRadius : 20,
shadowColor : '#'
},
image: {
width: 320,
height: 440,
borderRadius: 18,
resizeMode : "cover",
placeholder: "assets/images/loadingPlaceholder.gif"
},
gradient : {
position : "absolute",
top : 0,
left : 0,
right : 0,
height : 209,
}
});

@ -1,4 +1,4 @@
class Music {
export default class Music {
private id : string;
private name : string;
private artist : string;
@ -10,4 +10,5 @@ class Music {
this.artist = artist;
this.linkCover = linkCover;
}
}

@ -1,6 +1,7 @@
class Spot {
private userId : string;
public music : Music;;
public music : Music;
constructor(userId : string, music : Music){
this.userId = userId;
this.music = music;

@ -1,6 +1,6 @@
class User {
//attributes from DAFL
private idDafl : any;;
private idFlad : any;;
private idSpotify : any;
//constructors
constructor(){

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

@ -14,23 +14,17 @@ const SCREEN_WIDTH = Dimensions.get('window').width
interface CardProps {
title: string;
image: any;
onSwipe: (direction: "left" | "right") => void;
}
type ContextType = {
translateX: number;
translateY: number;
};
const Card = ({ title, image, onSwipe} : CardProps) => {
const Card : React.FC<CardProps> = ({ title, image} : CardProps) => {
const translateX = useSharedValue(0);
const translateY = useSharedValue(0);
const hapti = (() => {
// Haptics.NotificationFeedbackType.Success
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium)
});
const onGestureEvent = useAnimatedGestureHandler<
PanGestureHandlerGestureEvent,
ContextType
@ -47,10 +41,9 @@ const Card = ({ title, image, onSwipe} : CardProps) => {
// translateX.value = withSpring(0);
// translateY.value = withSpring(snapPoint(translateY.value,velocityY, snapPoints ))
if (translateX.value > 160) {
hapti()
onSwipe("right");
// onSwipe("right");
} else if (translateX.value < -160) {
onSwipe("left");
// onSwipe("left");
} else {
translateX.value = withSpring(0);
translateY.value = withSpring(0);
@ -75,8 +68,6 @@ const Card = ({ title, image, onSwipe} : CardProps) => {
( translateX.value,
[-SCREEN_WIDTH / 4, 0, SCREEN_WIDTH / 2],
[1, 0, 0]);
return {
opacity : opacityl,
};
@ -86,7 +77,7 @@ const Card = ({ title, image, onSwipe} : CardProps) => {
const opacityl = interpolate
( translateX.value,
[-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 4],
[0.85, 1, 1]);
[0.75, 1, 0.75]);
return {
opacity : opacityl,
@ -95,7 +86,7 @@ const Card = ({ title, image, onSwipe} : CardProps) => {
const opacDStyle = useAnimatedStyle(() => {
const opacityl = interpolate
( translateY.value,
[-SCREEN_HEIGHT / 4, 0, SCREEN_HEIGHT / 4],
[-SCREEN_HEIGHT / 4, 0, SCREEN_HEIGHT / 2],
[0, 0, 1]);
return {
opacity : opacityl,
@ -133,9 +124,7 @@ const Card = ({ title, image, onSwipe} : CardProps) => {
return (
<View>
<PanGestureHandler onGestureEvent={onGestureEvent}>
<Animated.View style={[ rStyle, styles.card,opacCStyle, ]} >
<Animated.View style={[ rStyle, styles.card,opacCStyle ]}>
<Animated.View
style={[{
// transform: [{ rotate: "30deg" }],
@ -144,7 +133,7 @@ const Card = ({ title, image, onSwipe} : CardProps) => {
},opacRStyle]}
>
<Image style={[{alignSelf : "center"}]}
source={require('../assets/icons/icon_dislike.png')}
source={require('../assets/icons/icons/icon_dislike.png')}
/>
</Animated.View>
<Animated.View
@ -156,7 +145,7 @@ const Card = ({ title, image, onSwipe} : CardProps) => {
},opacLStyle]}
>
<Image style={[{alignSelf : "center"}]}
source={require('../assets/icons/icon_like.png')}
source={require('../assets/icons/icons/icon_like.png')}
/>
</Animated.View>
@ -171,7 +160,7 @@ const Card = ({ title, image, onSwipe} : CardProps) => {
>
<Image style={[{alignSelf : "center",width: 126.27,
height: 118.64, }]}
source={require('../assets/icons/icon_discovery.png')}
source={require('../assets/icons/icons/icon_discovery.png')}
/>
</Animated.View>
@ -187,8 +176,7 @@ const styles = StyleSheet.create({
card : {
justifyContent : 'center',
alignItems : 'center',
borderColor : 'red',
borderWidth : 3,
},
image : {
borderRadius : 24,
@ -202,6 +190,3 @@ const styles = StyleSheet.create({
export default Card;

@ -4,7 +4,7 @@ import Animated,{ Extrapolate, interpolate, useAnimatedGestureHandler, useAnimat
import { PanGestureHandler, PanGestureHandlerGestureEvent } from 'react-native-gesture-handler';
import * as Haptics from 'expo-haptics';
import Icons from '../../assets/icons/icon';
import Icons from '../../assets/icons/icons/icon';
import Rive, { Fit, RiveRef } from 'rive-react-native';
const {width : wWidht} = Dimensions.get("window");

@ -1,12 +1,12 @@
export const cards = [{
name : "blue",
sourceUrl : "https://cdns-images.dzcdn.net/images/artist/399e7e760d8fedf3cc2891e9c0c41658/200x200-000000-80-0-0.jpg",
index : 3
},
{
name : "her",
sourceUrl : "https://images.unsplash.com/photo-1484589065579-248aad0d8b13?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1359&q=80",
index : 3
}
]
name : "blue",
sourceUrl : "https://i.ebayimg.com/images/g/rY0AAOSw97djEo2C/s-l500.jpg",
index : 3
},
{
name : "her",
sourceUrl : "https://i.ebayimg.com/images/g/rY0AAOSw97djEo2C/s-l500.jpg",
index : 3
}
]

@ -4,6 +4,7 @@ import Home from '../screens/spot';
import FavoritePage from '../screens/favoritePage';
import { createStackNavigator } from '@react-navigation/stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
// import Spot from '../screens/spot';
export default function StackNavigation() {
const Stack = createBottomTabNavigator();
@ -12,10 +13,10 @@ export default function StackNavigation() {
<Stack.Navigator initialRouteName="Home"
screenOptions={{
}}>
}} >
<Stack.Screen
name="Home"
component={FavoritePage}
component={Home}
options={{ headerShown: false }}
/>
<Stack.Screen

@ -13,10 +13,12 @@
"@react-navigation/native": "^6.1.3",
"@react-navigation/native-stack": "^6.9.8",
"@react-navigation/stack": "^6.3.12",
"expo": "~47.0.12",
"expo-cli": "^6.2.1",
"@reduxjs/toolkit": "^1.9.2",
"@types/react-redux": "^7.1.25",
"axios": "^1.2.6",
"expo": "~47.0.12",
"expo-auth-session": "~3.8.0",
"expo-cli": "^6.2.1",
"expo-haptics": "~12.0.1",
"expo-linear-gradient": "~12.0.1",
"expo-location": "~15.0.1",
@ -31,6 +33,8 @@
"react-native-safe-area-context": "4.4.1",
"react-native-screens": "~3.18.0",
"react-native-web": "~0.18.9",
"react-redux": "^8.0.5",
"redux": "^4.2.1",
"rive-react-native": "^3.0.41"
},
"devDependencies": {

@ -2,7 +2,7 @@ import React, {Component} from 'react';
import { Animated, StyleSheet, Text, View, FlatList, ScrollView, TouchableHighlight } from 'react-native';
import Card from '../components/Card';
import CardMusic from '../components/CardMusic';
import Music from '../model/Music'
import Music from '../Model/Music'
export default function favoritePage() {
const MUSIC_LIST : Music[] = [

@ -6,7 +6,7 @@ import * as AuthSession from 'expo-auth-session';
import Card from '../components/Card';
import axios from 'axios';
import { cards as cardArray } from '../FakeData/data'
import { cards as cardArray } from '../data/data'
import FladButton from '../components/button/button';
import * as WebBrowser from 'expo-web-browser';
import { makeRedirectUri, useAuthRequest } from 'expo-auth-session';

@ -5,7 +5,7 @@ import * as Haptics from 'expo-haptics';
import Card from '../components/Card';
import { cards as cardArray } from '../FakeData/data'
import { cards as cardArray } from '../data/data'
import FladButton from '../components/button/button';
import axios from 'axios';
@ -89,69 +89,65 @@ export default function Spot() {
const onSwipe = (index: number, direction: 'left' | 'right') => {
if (direction === 'right') {
// Swiped right
console.log("===================")
} else if (direction === 'left') {
// Swiped left
}
// update the state of the cards state when it remove thisy
setCards(cards.filter((_, i) => i !== index));
setcurrentCard(cards[cards.length -1]);
};
const hapti = (() => {
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Heavy)
getValueFor(MY_SECURE_AUTH_STATE_KEY)
.then(key => { (key != null) ? getUserData(key) :console.log("error key is nullll") } ) ;
// Haptics.NotificationFeedbackType.Success
});
// const hapti = (() => {
// Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Heavy)
// getValueFor(MY_SECURE_AUTH_STATE_KEY)
// .then(key => { (key != null) ? getUserData(key) :console.log("error key is nullll") } ) ;
// // Haptics.NotificationFeedbackType.Success
// });
////////////////////////////////////////////////////////////////
const [locationData, setLocationData] = useState<LocationData>();
const [prevLocationData, setPrevLocationData] = useState<LocationData>();
const [nearbyUsers, setNearbyUsers] = useState<NearbyUser[]>([]);
const [currentMusic, setCurrentMusic] = useState<string>("");
async function getLocation() {
var { status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') {
console.log('Permission to access location was denied');
return;
}
let currentLocation = await Location.getCurrentPositionAsync({});
setLocationData({
latitude: currentLocation.coords.latitude,
longitude: currentLocation.coords.longitude,
timestamp: currentLocation.timestamp
});
};
async function sendLocationToServer() {
getLocation();
if (!locationData) return;
if (prevLocationData && locationData.latitude === prevLocationData.latitude && locationData.longitude === prevLocationData.longitude) {
return;
}
try {
const response = await axios.post(
'http://localhost/api/users/david/nextToMe',
locationData
);
if (response.status !== 200) {
throw new Error('Failed to send location to server');
}
setPrevLocationData(locationData);
setNearbyUsers(response.data);
} catch (error) {
console.error(error);
}
};
// const [locationData, setLocationData] = useState<LocationData>();
// const [prevLocationData, setPrevLocationData] = useState<LocationData>();
// const [nearbyUsers, setNearbyUsers] = useState<NearbyUser[]>([]);
// const [currentMusic, setCurrentMusic] = useState<string>("");
// async function getLocation() {
// var { status } = await Location.requestForegroundPermissionsAsync();
// if (status !== 'granted') {
// console.log('Permission to access location was denied');
// return;
// }
// let currentLocation = await Location.getCurrentPositionAsync({});
// setLocationData({
// latitude: currentLocation.coords.latitude,
// longitude: currentLocation.coords.longitude,
// timestamp: currentLocation.timestamp
// });
// };
// async function sendLocationToServer() {
// getLocation();
// if (!locationData) return;
// if (prevLocationData && locationData.latitude === prevLocationData.latitude && locationData.longitude === prevLocationData.longitude) {
// return;
// }
// try {
// const response = await axios.post(
// 'http://localhost/api/users/david/nextToMe',
// locationData
// );
// if (response.status !== 200) {
// throw new Error('Failed to send location to server');
// }
// setPrevLocationData(locationData);
// setNearbyUsers(response.data);
// } catch (error) {
// console.error(error);
// }
// };
setInterval(sendLocationToServer, 30000)
// setInterval(sendLocationToServer, 30000)
return (
<View style={styles.spot}>
<ImageBackground blurRadius={20}
style={{
@ -173,12 +169,11 @@ export default function Spot() {
<View key={card.name} style = {{ position:'absolute'
}} >
<Pressable onLongPress={hapti}>
<Pressable >
<Card
title={card.name}
image={card.sourceUrl}
onSwipe={(direction) => onSwipe(index, direction)}
/>
</Pressable>
{/* <Button
@ -210,6 +205,7 @@ export default function Spot() {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor : '#000'
}
})

Loading…
Cancel
Save