aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Backend/Api/Api/Controllers/PostController.cs22
-rw-r--r--Backend/Api/Api/Controllers/UserController.cs6
-rw-r--r--Backend/Api/Api/Interfaces/IPostService.cs3
-rw-r--r--Backend/Api/Api/Interfaces/IUserService.cs2
-rw-r--r--Backend/Api/Api/Models/Post.cs12
-rw-r--r--Backend/Api/Api/Services/PostService.cs98
-rw-r--r--Backend/Api/Api/Services/UserService.cs79
-rw-r--r--Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivitySinglePost.kt77
-rw-r--r--Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityUserProfile.kt157
-rw-r--r--Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentUserPostsProfileActivity.kt64
-rw-r--r--Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Interfaces/IBackendApi.kt7
-rw-r--r--Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Models/RatingData.kt11
-rw-r--r--Client/BrzoDoLokacije/app/src/main/res/layout/activity_user_profile.xml35
-rw-r--r--Client/BrzoDoLokacije/app/src/main/res/layout/fragment_user_posts_profile_activity.xml18
14 files changed, 508 insertions, 83 deletions
diff --git a/Backend/Api/Api/Controllers/PostController.cs b/Backend/Api/Api/Controllers/PostController.cs
index 3d7199c..03c3f81 100644
--- a/Backend/Api/Api/Controllers/PostController.cs
+++ b/Backend/Api/Api/Controllers/PostController.cs
@@ -92,14 +92,15 @@ namespace Api.Controllers
public async Task<ActionResult> addRating([FromBody] RatingReceive rating,string id)
{
var userid = await _userService.UserIdFromJwt();
- if (await _postService.AddOrReplaceRating(rating, userid))
- return Ok();
+ var rez = await _postService.AddOrReplaceRating(rating, userid);
+ if(rez != null)
+ return Ok(rez);
return BadRequest();
}
[HttpDelete("posts/{id}/removerating")]
[Authorize(Roles = "User")]
- public async Task<ActionResult> removeRating(string id)
+ public async Task<ActionResult<int>> removeRating(string id)
{
var userid = await _userService.UserIdFromJwt();
if (await _postService.RemoveRating(id,userid))
@@ -170,5 +171,20 @@ namespace Api.Controllers
return Ok(await _postService.Get10Best());
}
+
+ [HttpGet("posts/{id}/getUserPosts")]
+ [Authorize(Roles = "User")]
+ public async Task<ActionResult<List<PostSend>>> GetUsersPosts(string id)
+ {
+ return Ok(await _postService.GetUsersPosts(id));
+ }
+
+ [HttpGet("posts/recommended")]
+ [Authorize(Roles = "User")]
+ public async Task<ActionResult<List<PostSend>>> Recommended()
+ {
+ var userid = await _userService.UserIdFromJwt();
+ return Ok(await _postService.Recommended(userid));
+ }
}
}
diff --git a/Backend/Api/Api/Controllers/UserController.cs b/Backend/Api/Api/Controllers/UserController.cs
index ada0f35..cc45737 100644
--- a/Backend/Api/Api/Controllers/UserController.cs
+++ b/Backend/Api/Api/Controllers/UserController.cs
@@ -110,5 +110,11 @@ namespace Api.Controllers
return Ok(await _userService.CheckIfAlreadyFollow(id));
}
+ [HttpGet("{id}/unfollow")]
+ [Authorize(Roles = "User")]
+ public async Task<ActionResult<Boolean>> Unfollow(string id)
+ {
+ return Ok(await _userService.Unfollow(id));
+ }
}
}
diff --git a/Backend/Api/Api/Interfaces/IPostService.cs b/Backend/Api/Api/Interfaces/IPostService.cs
index 60781bb..96786bd 100644
--- a/Backend/Api/Api/Interfaces/IPostService.cs
+++ b/Backend/Api/Api/Interfaces/IPostService.cs
@@ -9,7 +9,7 @@ namespace Api.Interfaces
Task<List<PostSend>> getAllPosts();
Task<PostSend> getPostById(string id,string userid);
Task<PostSend> postToPostSend(Post post);
- Task<Boolean> AddOrReplaceRating(RatingReceive rating, string userid);
+ Task<RatingSend> AddOrReplaceRating(RatingReceive rating, string userid);
Task<Boolean> RemoveRating(string postid, string userid);
Task<CommentSend> AddComment(CommentReceive cmnt, string userid, string postid);
Task<List<CommentSend>> ListComments(string postid);
@@ -26,5 +26,6 @@ namespace Api.Interfaces
Task<List<PostSend>> Get10MostViewed();
Task<List<PostSend>> Get10Newest();
+ Task<List<PostSend>> Recommended(string userid);
}
} \ No newline at end of file
diff --git a/Backend/Api/Api/Interfaces/IUserService.cs b/Backend/Api/Api/Interfaces/IUserService.cs
index 21dcdc0..5f99733 100644
--- a/Backend/Api/Api/Interfaces/IUserService.cs
+++ b/Backend/Api/Api/Interfaces/IUserService.cs
@@ -33,5 +33,7 @@ namespace Api.Interfaces
Task<List<UserSend>> GetMyFollowings();
Task<Boolean> CheckIfAlreadyFollow(string id);
+ Task<Boolean> Unfollow(string id);
+
}
}
diff --git a/Backend/Api/Api/Models/Post.cs b/Backend/Api/Api/Models/Post.cs
index 0dc8158..dd007ec 100644
--- a/Backend/Api/Api/Models/Post.cs
+++ b/Backend/Api/Api/Models/Post.cs
@@ -49,6 +49,12 @@ namespace Api.Models
public string userId { get; set; }
public int rating { get; set; }
}
+ public class RatingSend
+ {
+ public int ratingscount { get; set; }
+ public double ratings { get; set; }
+ public int myrating { get; set; }
+ }
public class Comment
{
[BsonId]
@@ -102,4 +108,10 @@ namespace Api.Models
public int totalposts { get; set; }
public List<PostSend> posts { get; set; }
}
+
+ public class TagR
+ {
+ public int counter { get; set; }
+ public string tag { get; set; }
+ }
}
diff --git a/Backend/Api/Api/Services/PostService.cs b/Backend/Api/Api/Services/PostService.cs
index dcfd5e0..855b231 100644
--- a/Backend/Api/Api/Services/PostService.cs
+++ b/Backend/Api/Api/Services/PostService.cs
@@ -148,13 +148,34 @@ namespace Api.Services
return await postToPostSend(p);
}
- public async Task<Boolean> AddOrReplaceRating(RatingReceive rating,string userid)
+ public async Task<RatingSend> AddOrReplaceRating(RatingReceive rating,string userid) //0 return existing flag , -1 rating failed flag
{
Post p = await _posts.Find(post => post._id == rating.postId).FirstOrDefaultAsync();
if (p != null)
{
+ var tosend = new RatingSend();
+ var ps = await postToPostSend(p);
+ tosend.ratings = ps.ratings;
+ tosend.ratingscount = ps.ratingscount;
+
if (p.ownerId == userid)
- return false;
+ return null;
+ if(rating.rating == 0)// ako nema rating staviti 0
+ {
+ var r = p.ratings.Find(x => x.userId == userid);
+ if(r != null)
+ {
+ tosend.myrating=r.rating;
+ return tosend;
+ }
+ else
+ {
+ tosend.myrating = 0;
+ return tosend;
+ }
+ }
+ if(rating.rating<1 || rating.rating>5)
+ return null;
if(!p.ratings.Any(x => x.userId == userid))
{
Rating r = new Rating();
@@ -162,6 +183,7 @@ namespace Api.Services
r.userId = userid;
p.ratings.Add(r);
await _posts.ReplaceOneAsync(x => x._id == p._id, p);
+ tosend.myrating=rating.rating;
}
else
{
@@ -170,10 +192,15 @@ namespace Api.Services
r.rating = rating.rating;
p.ratings.Add(r);
await _posts.ReplaceOneAsync(x => x._id == p._id, p);
+ tosend.myrating = rating.rating;
}
- return true;
+ p = await _posts.Find(post => post._id == rating.postId).FirstOrDefaultAsync();
+ ps = await postToPostSend(p);
+ tosend.ratings = ps.ratings;
+ tosend.ratingscount = ps.ratingscount;
+ return tosend;
}
- return false;
+ return null;
}
public async Task<Boolean> RemoveRating(string postid, string userid)
{
@@ -440,5 +467,68 @@ namespace Api.Services
List<PostSend> newest = temp.OrderByDescending(o => o.createdAt).Take(10).ToList();
return newest;
}
+
+ public async Task<List<PostSend>> Recommended(string userid) // momgodb bloat bleh
+ {
+ List<PostSend> posts = await UserHistory(userid);
+ //TODO-LIMIT RECOMMENDED FOR POSTS FROM THIS MONTH ONLY
+ List<TagR> tags = new List<TagR>();
+ foreach (var post in posts)
+ {
+ if (post.tags != null)
+ {
+
+ foreach (var tagitem in post.tags)
+ {
+ if (!tags.Any(x => x.tag == tagitem))
+ {
+ var newtag = new TagR();
+ newtag.tag = tagitem;
+ newtag.counter = 1;
+ tags.Add(newtag);
+ }
+ else
+ {
+ var replace = tags.Find(x => x.tag == tagitem);
+ tags.Remove(replace);
+ replace.counter += 1;
+ tags.Add(replace);
+ }
+ }
+ }
+ }
+ var top5tags = tags.OrderByDescending(x => x.counter).Take(5).ToList();
+
+ var all = await _posts.Find(_ => true).ToListAsync();
+ var recent30 = new List<PostSend>();
+ var fiveoftop5tags = new List<PostSend>();
+ foreach (var elem in all)
+ {
+ if ((DateTime.Now - elem.createdAt).TotalDays < 30)
+ recent30.Add(await postToPostSend(elem));
+ }
+ recent30 = recent30.OrderByDescending(x => x.createdAt).ToList();
+ foreach (var tag in top5tags)
+ {
+ var five = new List<PostSend>();
+ foreach (var elem in recent30)
+ {
+ if (elem.tags != null)
+ {
+ if (elem.tags.Any(x => x == tag.tag))
+ five.Add(elem);
+ }
+ }
+ five = five.Take(5).ToList();
+ foreach(var elem in five)
+ {
+ fiveoftop5tags.Add(elem);
+ }
+ }
+
+ var taggedposts = new List<PostSend>();
+ taggedposts = fiveoftop5tags.Distinct().OrderByDescending(x => x.createdAt).ToList();
+ return taggedposts;
+ }
}
}
diff --git a/Backend/Api/Api/Services/UserService.cs b/Backend/Api/Api/Services/UserService.cs
index 7bfc24a..cc75533 100644
--- a/Backend/Api/Api/Services/UserService.cs
+++ b/Backend/Api/Api/Services/UserService.cs
@@ -6,6 +6,7 @@ using System.Security.Claims;
using MimeKit;
using MailKit.Net.Smtp;
using DnsClient;
+using MongoDB.Bson;
namespace Api.Services
{
@@ -380,6 +381,18 @@ namespace Api.Services
return tosend;
}
+ public async Task<Boolean> updateUserFollowerFollowingCount(List<string> followers,List <string> followings,string userId)
+ {
+ User u = await _users.Find(user => user._id == userId).FirstOrDefaultAsync();
+ if(u!= null)
+ {
+ u.followersCount = followers.Count();
+ u.followingCount = followings.Count();
+ return true;
+ }
+ return false;
+ }
+
public async Task<Boolean> AddFollower(string followerId)
{
string id = null;
@@ -392,14 +405,29 @@ namespace Api.Services
if (id != null && followerId!=null)
{
- if (u.followers == null)
- u.followers = new List<string>();
- u.followers.Add(followerId);
- if (f.following == null)
- f.following = new List<string>();
- f.following.Add(id);
+ if (f.followers == null)
+ {
+ f.followers = new List<string>();
+ f.followersCount = 0;
+ }
+ f.followers.Add(id);
+ f.followersCount =f.followers.Count();
+
+
+ if (u.following == null)
+ {
+ u.following = new List<string>();
+ u.followingCount = 0;
+ }
+ u.following.Add(followerId);
+ u.followingCount =u.following.Count();
+
_users.ReplaceOne(user=>user._id==id, u);
_users.ReplaceOne(user => user._id == followerId, f);
+
+ // updateUserFollowerFollowingCount(u.followers, u.following, u._id);
+ //updateUserFollowerFollowingCount(f.followers, f.following, f._id);
+
return true;
}
@@ -543,5 +571,42 @@ namespace Api.Services
return false;
}
- }
+
+ public async Task<bool> Unfollow(string id)
+ {
+ string myId = null;
+
+ if (_httpContext.HttpContext.User.FindFirstValue("id") != null)
+ {
+ myId = _httpContext.HttpContext.User.FindFirstValue("id").ToString();
+ }
+
+ User u = await _users.Find(user => user._id == myId).FirstOrDefaultAsync();
+ User f = await _users.Find(user => user._id == id).FirstOrDefaultAsync();
+
+ if (u != null)
+ {
+ if (u.following != null && f.followers!=null)
+ {
+ u.following.Remove(f._id);
+ u.followingCount=u.following.Count();
+ u.followersCount = u.followers.Count();
+
+
+ f.followers.Remove(u._id);
+ f.followersCount =f.followers.Count();
+ f.followingCount =f.following.Count();
+
+ _users.ReplaceOne(user => user._id == myId, u);
+ _users.ReplaceOne(user => user._id == id, f);
+
+ //updateUserFollowerFollowingCount(u.followers, u.following, u._id);
+ //updateUserFollowerFollowingCount(f.followers, f.following, f._id);
+ return true;
+ }
+
+ }
+ return false;
+ }
+ }
}
diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivitySinglePost.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivitySinglePost.kt
index d1ec76b..e1c2f80 100644
--- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivitySinglePost.kt
+++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivitySinglePost.kt
@@ -3,9 +3,12 @@ package com.example.brzodolokacije.Activities
import android.content.Intent
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
+import android.media.Image
import android.os.Bundle
import android.preference.PreferenceManager
+import android.provider.ContactsContract.CommonDataKinds.Im
import android.util.Log
+import android.widget.ImageButton
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
@@ -66,6 +69,9 @@ class ActivitySinglePost : AppCompatActivity() {
setRatingListeners()
translateOwnerIdToName(post.ownerId)
+ val alreadyrated= RatingReceive(starNumber.toInt(),post._id)
+ requestAddRating(alreadyrated)
+
binding.tvUser.setOnClickListener {
val intent: Intent = Intent(this@ActivitySinglePost,ActivityUserProfile::class.java)
var b= Bundle()
@@ -115,13 +121,29 @@ class ActivitySinglePost : AppCompatActivity() {
recyclerViewComments!!.adapter= adapterComments
}
- fun setRatingListeners(){
- val emptyStar=R.drawable.empty_star
- val fullStar=R.drawable.full_star
- //var starlist:List<ImageButton> = mutableListOf()
+ fun setRatingListeners() {
+ val emptyStar = R.drawable.empty_star
+ val fullStar = R.drawable.full_star
+ /*var starlist: ArrayList<ImageButton> = arrayListOf()
+ starlist.add(findViewById(R.id.rateStar1) as ImageButton)
+ starlist.add(findViewById(R.id.rateStar2) as ImageButton)
+ starlist.add(findViewById(R.id.rateStar3) as ImageButton)
+ starlist.add(findViewById(R.id.rateStar4) as ImageButton)
+ starlist.add(findViewById(R.id.rateStar5) as ImageButton)
+ for (i in 0..4) {
+ starlist[i].setOnClickListener {
+ for (j in 1..i) {
+ starlist[j].setImageResource(fullStar)
+ }
+ for (k in i..5) {
+ starlist[k].setImageResource(emptyStar)
+ }
+ starNumber = i+1;
+ }
+ }*/
binding.rateStar1.setOnClickListener {
- Toast.makeText(this,"kliknuta prva zvezdica",Toast.LENGTH_SHORT).show()
+ //Toast.makeText(this,"kliknuta prva zvezdica",Toast.LENGTH_SHORT).show()
binding.rateStar1.setImageResource(fullStar)
binding.rateStar2.setImageResource(emptyStar)
binding.rateStar3.setImageResource(emptyStar)
@@ -130,7 +152,7 @@ class ActivitySinglePost : AppCompatActivity() {
starNumber=1
}
binding.rateStar2.setOnClickListener {
- Toast.makeText(this,"kliknuta druga zvezdica",Toast.LENGTH_SHORT).show()
+ //Toast.makeText(this,"kliknuta druga zvezdica",Toast.LENGTH_SHORT).show()
binding.rateStar1.setImageResource(fullStar)
binding.rateStar2.setImageResource(fullStar)
binding.rateStar3.setImageResource(emptyStar)
@@ -139,7 +161,7 @@ class ActivitySinglePost : AppCompatActivity() {
starNumber=2
}
binding.rateStar3.setOnClickListener {
- Toast.makeText(this,"kliknuta treca zvezdica",Toast.LENGTH_SHORT).show()
+ //Toast.makeText(this,"kliknuta treca zvezdica",Toast.LENGTH_SHORT).show()
binding.rateStar1.setImageResource(fullStar)
binding.rateStar2.setImageResource(fullStar)
binding.rateStar3.setImageResource(fullStar)
@@ -148,7 +170,7 @@ class ActivitySinglePost : AppCompatActivity() {
starNumber=3
}
binding.rateStar4.setOnClickListener {
- Toast.makeText(this,"kliknuta cetvrta zvezdica",Toast.LENGTH_SHORT).show()
+ //Toast.makeText(this,"kliknuta cetvrta zvezdica",Toast.LENGTH_SHORT).show()
binding.rateStar1.setImageResource(fullStar)
binding.rateStar2.setImageResource(fullStar)
binding.rateStar3.setImageResource(fullStar)
@@ -157,7 +179,7 @@ class ActivitySinglePost : AppCompatActivity() {
starNumber=4
}
binding.rateStar5.setOnClickListener {
- Toast.makeText(this,"kliknuta peta zvezdica",Toast.LENGTH_SHORT).show()
+ //Toast.makeText(this,"kliknuta peta zvezdica",Toast.LENGTH_SHORT).show()
binding.rateStar1.setImageResource(fullStar)
binding.rateStar2.setImageResource(fullStar)
binding.rateStar3.setImageResource(fullStar)
@@ -194,6 +216,7 @@ class ActivitySinglePost : AppCompatActivity() {
request.enqueue(object : retrofit2.Callback<CommentSend?> {
override fun onResponse(call: Call<CommentSend?>, response: Response<CommentSend?>) {
if(response.isSuccessful){
+
var newComment=response.body()!!
requestGetComments(newComment)
binding.NewComment.text.clear()
@@ -251,15 +274,31 @@ class ActivitySinglePost : AppCompatActivity() {
val postApi= RetrofitHelper.getInstance()
val token= SharedPreferencesHelper.getValue("jwt", this@ActivitySinglePost)
val request=postApi.addRating("Bearer "+token,post._id,rating)
- request.enqueue(object : retrofit2.Callback<ResponseBody?> {
- override fun onResponse(call: Call<ResponseBody?>, response: Response<ResponseBody?>) {
+ request.enqueue(object : retrofit2.Callback<RatingData?> {
+ override fun onResponse(call: Call<RatingData?>, response: Response<RatingData?>) {
if(response.isSuccessful){
- //zasad hardkodovano, zameniti te vrednosti sa brojem ocena kada se doda
- post.ratings=((post.ratings)*10+rating.rating)/11
- binding.tvRating.text=String.format("%.2f",post.ratings)
- Toast.makeText(
- this@ActivitySinglePost, "prosao zahtev", Toast.LENGTH_LONG
- ).show()
+ var data=response.body()!!
+ binding.tvRating.text=String.format("%.2f",data.ratings)
+ binding.tvNumberOfRatings.text=String.format("%d",data.ratingscount)
+ Log.d("--------------",data.ratings.toString()+" "+data.ratingscount.toString())
+ when(data.myrating){
+ 1->binding.rateStar1.performClick()
+ 2->binding.rateStar2.performClick()
+ 3->binding.rateStar3.performClick()
+ 4->binding.rateStar4.performClick()
+ 5->binding.rateStar5.performClick()
+ else->{
+ val emptyStar = R.drawable.empty_star
+ binding.rateStar1.setImageResource(emptyStar)
+ binding.rateStar2.setImageResource(emptyStar)
+ binding.rateStar3.setImageResource(emptyStar)
+ binding.rateStar4.setImageResource(emptyStar)
+ binding.rateStar5.setImageResource(emptyStar)
+ }
+ }
+ /*Toast.makeText(
+ this@ActivitySinglePost, "prosao zahtev", Toast.LENGTH_LONG
+ ).show()*/
}else{
if(response.errorBody()!=null)
Log.d("main1",response.errorBody().toString())
@@ -268,7 +307,7 @@ class ActivitySinglePost : AppCompatActivity() {
}
- override fun onFailure(call: Call<ResponseBody?>, t: Throwable) {
+ override fun onFailure(call: Call<RatingData?>, t: Throwable) {
Log.d("main2",t.message.toString())
}
})
@@ -284,7 +323,7 @@ class ActivitySinglePost : AppCompatActivity() {
tvLocationParent.invalidate()
tvRating.text=post.ratings.toString()
tvRating.invalidate()
- tvNumberOfRatings.text=post.ratings.toString()
+ tvNumberOfRatings.text=post.ratingscount.toString()
tvNumberOfRatings.invalidate()
tvDescription.text=post.description
tvDescription.invalidate()
diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityUserProfile.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityUserProfile.kt
index c03dbd3..5119da9 100644
--- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityUserProfile.kt
+++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Activities/ActivityUserProfile.kt
@@ -1,17 +1,15 @@
package com.example.brzodolokacije.Activities
import android.annotation.SuppressLint
-import android.graphics.Color
-import android.graphics.PorterDuff
-import android.graphics.drawable.Drawable
import android.os.Bundle
import android.util.Log
import android.widget.*
import androidx.appcompat.app.AppCompatActivity
-import androidx.core.content.ContextCompat
-import androidx.fragment.app.Fragment
+import androidx.core.view.isVisible
+import androidx.fragment.app.FragmentManager
+import androidx.fragment.app.FragmentTransaction
import com.bumptech.glide.Glide
-import com.example.brzodolokacije.Fragments.FragmentShowUserPosts
+import com.example.brzodolokacije.Fragments.FragmentUserPostsProfileActivity
import com.example.brzodolokacije.Models.UserReceive
import com.example.brzodolokacije.R
import com.example.brzodolokacije.R.*
@@ -21,7 +19,6 @@ import com.google.gson.Gson
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
-import java.security.AccessController.getContext
class ActivityUserProfile : AppCompatActivity() {
@@ -35,9 +32,9 @@ class ActivityUserProfile : AppCompatActivity() {
private lateinit var fragmentContainer: FrameLayout
private lateinit var userObject:UserReceive
private lateinit var openChat:ImageButton
+ private lateinit var unfollowUser:Button
- private lateinit var followersList: MutableList<UserReceive>
- private lateinit var followingList: MutableList<UserReceive>
+ private var follow:Boolean=false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -49,6 +46,7 @@ class ActivityUserProfile : AppCompatActivity() {
followingNumber=findViewById(id.tvActivityUserProfileFollowNo)
profilePicture=findViewById(id.tvActivityProfileProfilePicture)
followUser=findViewById(id.btnActivityUserProfileFollow)
+ unfollowUser=findViewById(id.btnActivityUserProfileUnFollow)
showUserPosts=findViewById(id.btnActivityUserProfileShowPosts)
fragmentContainer=findViewById(id.flActivityProfileFragmentContainer)
openChat=findViewById(id.activityUserProfileOpenChat)
@@ -74,42 +72,79 @@ class ActivityUserProfile : AppCompatActivity() {
}
}
+
checkIfAlreadyFollow()
+ updateUserData()
followUser.setOnClickListener{
+ val api = RetrofitHelper.getInstance()
+ val token = SharedPreferencesHelper.getValue("jwt", this@ActivityUserProfile)
+ var data = api.addFollower("Bearer " + token, userObject._id);
+ data.enqueue(object : Callback<Boolean> {
+ override fun onResponse(
+ call: Call<Boolean>,
+ response: Response<Boolean>
+ ) {
+ unfollowUser.isVisible=true
+ unfollowUser.isClickable=true
+ unfollowUser.isEnabled=true
+ followUser.isVisible=false
+ followUser.isClickable=false
+ followUser.isEnabled=false
+ updateUserData()
+
+ Toast.makeText(
+ this@ActivityUserProfile, "PRATITE KORISNIKA", Toast.LENGTH_LONG
+ ).show();
+ }
+
+ override fun onFailure(call: Call<Boolean>, t: Throwable) {
+ Toast.makeText(
+ this@ActivityUserProfile, t.toString(), Toast.LENGTH_LONG
+ ).show();
+ }
+ })
- checkIfAlreadyFollow()
-
+ }
+ unfollowUser.setOnClickListener {
+ val api = RetrofitHelper.getInstance()
+ val token = SharedPreferencesHelper.getValue("jwt", this@ActivityUserProfile)
+ var data = api.unfollow("Bearer " + token, userObject._id);
+ data.enqueue(object : Callback<Boolean> {
+ override fun onResponse(
+ call: Call<Boolean>,
+ response: Response<Boolean>
+ ) {
+ unfollowUser.isVisible=false
+ unfollowUser.isClickable=false
+ unfollowUser.isEnabled=false
+ followUser.isVisible=true
+ followUser.isClickable=true
+ followUser.isEnabled=true
+ updateUserData()
+ Toast.makeText(
+ this@ActivityUserProfile, "VIŠE NE PRATITE KORISNIKA", Toast.LENGTH_LONG
+ ).show();
+ }
+
+ override fun onFailure(call: Call<Boolean>, t: Throwable) {
+ Toast.makeText(
+ this@ActivityUserProfile, t.toString(), Toast.LENGTH_LONG
+ ).show();
+ }
+ })
- val api = RetrofitHelper.getInstance()
- val token= SharedPreferencesHelper.getValue("jwt", this@ActivityUserProfile)
- var data=api.addFollower("Bearer "+token,userObject._id);
- data.enqueue(object : Callback<Boolean> {
- override fun onResponse(
- call: Call<Boolean>,
- response: Response<Boolean>
- ) {
- Toast.makeText(
- this@ActivityUserProfile, "PRATITE KORISNIKA", Toast.LENGTH_LONG
- ).show();
- }
- override fun onFailure(call: Call<Boolean>, t: Throwable) {
- Toast.makeText(
- this@ActivityUserProfile, t.toString(), Toast.LENGTH_LONG
- ).show();
- }
- })
}
showUserPosts.setOnClickListener {
- val bundle = Bundle()
- bundle.putString("user", Gson().toJson(userObject))
- val fragment = Fragment()
- fragment.arguments = bundle
- getSupportFragmentManager().beginTransaction()
- .replace(id.flActivityProfileFragmentContainer,FragmentShowUserPosts()).commit()
-
+ var fm: FragmentTransaction =supportFragmentManager.beginTransaction()
+ val fragment = FragmentUserPostsProfileActivity()
+ val b = Bundle()
+ b.putString("userId", userObject._id.toString())
+ fragment.arguments = b
+ fm.replace(R.id.flActivityProfileFragmentContainer, fragment)
+ fm.commit()
}
}
@@ -132,15 +167,34 @@ class ActivityUserProfile : AppCompatActivity() {
}
var follow = response.body()!!
if(follow){
+
Log.d("success","follow")
- followUser.setCompoundDrawablesWithIntrinsicBounds(drawable.ic_outline_person_remove_24,0,0,0)
+ /*followUser.setCompoundDrawablesWithIntrinsicBounds(drawable.ic_outline_person_remove_24,0,0,0)
followUser.text="Ne prati više"
-
+ follow=false
+ */
+ unfollowUser.isVisible=true
+ unfollowUser.isClickable=true
+ unfollowUser.isEnabled=true
+ followUser.isVisible=false
+ followUser.isClickable=false
+ followUser.isEnabled=false
}
- if(!follow){
+ else{
Log.d("success","not follow")
- followUser.setCompoundDrawablesWithIntrinsicBounds(drawable.ic_outline_person_add_alt_24,0,0,0)
+ /*followUser.setCompoundDrawablesWithIntrinsicBounds(drawable.ic_outline_person_add_alt_24,0,0,0)
followUser.text="Prati"
+ follow=true
+ */
+
+ unfollowUser.isVisible=false
+ unfollowUser.isClickable=false
+ unfollowUser.isEnabled=false
+ followUser.isVisible=true
+ followUser.isClickable=true
+ followUser.isEnabled=true
+
+
}
}
@@ -148,7 +202,28 @@ class ActivityUserProfile : AppCompatActivity() {
}
- fun checkIfAlreadyFollowChangeButton(){
+ fun updateUserData(){
+ val api = RetrofitHelper.getInstance()
+ val token = SharedPreferencesHelper.getValue("jwt", this@ActivityUserProfile)
+ var data = api.getProfileFromId("Bearer " + token, userObject._id);
+ data.enqueue(object : Callback<UserReceive> {
+ override fun onResponse(
+ call: Call<UserReceive>,
+ response: Response<UserReceive>
+ ) {
+ var userData=response.body()!!
+ name.text=userData.name
+ postsNumber.text=userData.postNumber.toString()
+ followersNumber.text=userData.followersCount.toString()
+ followingNumber.text=userData.followingCount.toString()
+ }
+ override fun onFailure(call: Call<UserReceive>, t: Throwable) {
+ Toast.makeText(
+ this@ActivityUserProfile, t.toString(), Toast.LENGTH_LONG
+ ).show();
+ }
+ })
}
+
} \ No newline at end of file
diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentUserPostsProfileActivity.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentUserPostsProfileActivity.kt
new file mode 100644
index 0000000..d841430
--- /dev/null
+++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentUserPostsProfileActivity.kt
@@ -0,0 +1,64 @@
+package com.example.brzodolokacije.Fragments
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.recyclerview.widget.GridLayoutManager
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.example.brzodolokacije.Adapters.MyPostsAdapter
+import com.example.brzodolokacije.Adapters.ShowPostsHomePageAdapter
+import com.example.brzodolokacije.Models.PostPreview
+import com.example.brzodolokacije.R
+import com.example.brzodolokacije.Services.RetrofitHelper
+import com.example.brzodolokacije.Services.SharedPreferencesHelper
+import retrofit2.Call
+import retrofit2.Callback
+import retrofit2.Response
+
+
+class FragmentUserPostsProfileActivity : Fragment() {
+ private lateinit var recyclerView: RecyclerView
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ // Inflate the layout for this fragment
+ var view =inflater.inflate(R.layout.fragment_user_posts_profile_activity, container, false)
+
+ recyclerView=view.findViewById(R.id.rvFragmentUserPostsProfileActivity)
+
+ val bundle = arguments
+ val userId = bundle!!.getString("userId")
+
+ val api = RetrofitHelper.getInstance()
+ val token = SharedPreferencesHelper.getValue("jwt", requireActivity())
+ var data = api.getUsersPosts("Bearer " + token, userId!!);
+ data.enqueue(object : Callback<MutableList<PostPreview>> {
+ override fun onResponse(
+ call: Call<MutableList<PostPreview>>,
+ response: Response<MutableList<PostPreview>>
+ ) {
+ if (response.body() == null) {
+ return
+ }
+ var posts = response.body()!!.toMutableList<PostPreview>()
+ recyclerView.apply {
+ layoutManager= GridLayoutManager(requireContext(),3,
+ GridLayoutManager.VERTICAL,false)
+ adapter= MyPostsAdapter(requireActivity(),posts)
+ }
+ }
+
+ override fun onFailure(call: Call<MutableList<PostPreview>>, t: Throwable) {
+ }
+ })
+
+
+ return view
+ }
+
+
+} \ No newline at end of file
diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Interfaces/IBackendApi.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Interfaces/IBackendApi.kt
index ce8d7e3..f753f43 100644
--- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Interfaces/IBackendApi.kt
+++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Interfaces/IBackendApi.kt
@@ -38,7 +38,7 @@ interface IBackendApi {
,@Part("tags") tags:RequestBody
):Call<PostPreview>
@POST("api/Post/posts/{id}/addrating")
- fun addRating(@Header("Authorization") authHeader:String,@Path("id") id:String,@Body rating: RatingReceive):Call<ResponseBody>
+ fun addRating(@Header("Authorization") authHeader:String,@Path("id") id:String,@Body rating: RatingReceive):Call<RatingData>
@POST("api/Post/posts/{id}/addcomment")
fun addComment(@Header("Authorization") authHeader:String,@Path("id") id:String,@Body rating: CommentReceive):Call<CommentSend>
@GET("api/Post/posts/{id}/listcomments")
@@ -101,4 +101,9 @@ interface IBackendApi {
@GET("/api/user/{id}/checkIfAlreadyFollow")
fun checkIfAlreadyFollow(@Header("Authorization") authHeader:String,@Path("id") id:String):Call<Boolean>
+ @GET("/api/user/{id}/unfollow")
+ fun unfollow(@Header("Authorization") authHeader:String,@Path("id") id:String):Call<Boolean>
+
+ @GET("api/Post/posts/{id}/getUserPosts")
+ fun getUsersPosts(@Header("Authorization") authHeader:String,@Path("id") id:String):Call<MutableList<PostPreview>>
} \ No newline at end of file
diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Models/RatingData.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Models/RatingData.kt
new file mode 100644
index 0000000..630c325
--- /dev/null
+++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Models/RatingData.kt
@@ -0,0 +1,11 @@
+package com.example.brzodolokacije.Models
+
+import android.os.Parcelable
+import kotlinx.android.parcel.Parcelize
+
+@Parcelize
+data class RatingData(
+ var ratings:Double,
+ var ratingscount:Int,
+ var myrating:Int
+):Parcelable \ No newline at end of file
diff --git a/Client/BrzoDoLokacije/app/src/main/res/layout/activity_user_profile.xml b/Client/BrzoDoLokacije/app/src/main/res/layout/activity_user_profile.xml
index a446f9a..bb917cf 100644
--- a/Client/BrzoDoLokacije/app/src/main/res/layout/activity_user_profile.xml
+++ b/Client/BrzoDoLokacije/app/src/main/res/layout/activity_user_profile.xml
@@ -128,7 +128,7 @@
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/divider"
- app:layout_constraintVertical_bias="1.0"></FrameLayout>
+ app:layout_constraintVertical_bias="0.0"></FrameLayout>
<TableLayout
@@ -228,22 +228,44 @@
<Button
android:id="@+id/btnActivityUserProfileFollow"
- android:layout_width="0dp"
+ android:layout_width="280dp"
android:layout_height="30dp"
android:layout_marginStart="16dp"
- android:layout_marginEnd="8dp"
+ android:clickable="true"
android:drawableLeft="@drawable/ic_outline_person_add_alt_24"
- android:text="PRATI"
android:insetTop="0dp"
android:insetBottom="0dp"
+ android:backgroundTint="@color/button_main"
+ android:text="PRATI"
+ android:visibility="visible"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintVertical_bias="0.13"
app:shapeAppearanceOverlay="@style/Circular"
+ tools:ignore="TouchTargetSizeCheck" />
+
+ <Button
+
+ android:id="@+id/btnActivityUserProfileUnFollow"
+ android:layout_width="280dp"
+ android:layout_height="30dp"
+ android:layout_marginStart="16dp"
+ android:clickable="false"
+ android:drawableLeft="@drawable/ic_outline_person_remove_24"
+ android:insetTop="0dp"
+ android:insetBottom="0dp"
+ android:text="NE PRATI više"
+ android:backgroundTint="@color/unfollow"
+
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toStartOf="@+id/activityUserProfileOpenChat"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.13"
+ app:shapeAppearanceOverlay="@style/Circular"
tools:ignore="TouchTargetSizeCheck" />
+
<ImageButton
android:id="@+id/activityUserProfileOpenChat"
android:layout_width="35dp"
@@ -252,11 +274,10 @@
android:layout_marginEnd="16dp"
android:height="40dp"
android:background="@drawable/rounded_button"
- android:backgroundTint="#4DB6AC"
+ android:backgroundTint="@color/button_main"
android:src="@drawable/ic_round_message_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toEndOf="@+id/btnActivityUserProfileFollow"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
app:shapeAppearanceOverlay="@style/Circular"
diff --git a/Client/BrzoDoLokacije/app/src/main/res/layout/fragment_user_posts_profile_activity.xml b/Client/BrzoDoLokacije/app/src/main/res/layout/fragment_user_posts_profile_activity.xml
new file mode 100644
index 0000000..2c5012e
--- /dev/null
+++ b/Client/BrzoDoLokacije/app/src/main/res/layout/fragment_user_posts_profile_activity.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".Fragments.FragmentUserPostsProfileActivity">
+
+ <!-- TODO: Update blank fragment layout -->
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/rvFragmentUserPostsProfileActivity"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+</FrameLayout> \ No newline at end of file