Skip to content

Commit

Permalink
activity Page fixed (#219)
Browse files Browse the repository at this point in the history
Co-authored-by: adescoteaux1 <[email protected]>
  • Loading branch information
adescoteaux1 and adescoteaux1 authored Dec 4, 2024
1 parent c1bd7f5 commit df3e235
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 59 deletions.
131 changes: 104 additions & 27 deletions backend/internal/storage/postgres/schema/review.go
Original file line number Diff line number Diff line change
Expand Up @@ -412,54 +412,131 @@ func (r *ReviewRepository) GetUserReviewsOfMedia(ctx context.Context, media_type

}

func (r *ReviewRepository) GetReviewsByUserID(ctx context.Context, id string) ([]*models.Review, error) {
func (r *ReviewRepository) GetReviewsByUserID(ctx context.Context, userId string) ([]*models.Preview, error) {

rows, err := r.Query(ctx, "SELECT id, user_id, media_id, media_type, rating, title, comment, created_at, updated_at, draft FROM review WHERE user_id = $1 ORDER BY updated_at DESC", id)
query := `
SELECT
r.id,
r.user_id,
u.username,
u.display_name,
u.profile_picture,
r.media_type,
r.media_id,
r.rating,
r.title,
r.comment,
r.created_at,
r.updated_at,
COALESCE(a.cover, t.cover) AS media_cover,
COALESCE(a.title, t.title) AS media_title,
COALESCE(a.artists, t.artists) AS media_artist,
ARRAY_AGG(tag.name) FILTER (WHERE tag.name IS NOT NULL) AS tags
FROM review r
INNER JOIN "user" u ON u.id = r.user_id
LEFT JOIN (
SELECT t.title, t.id, STRING_AGG(ar.name, ', ') AS artists, cover
FROM track t
JOIN track_artist ta on t.id = ta.track_id
JOIN artist ar ON ta.artist_id = ar.id
JOIN album a on t.album_id = a.id
GROUP BY t.id, cover, t.title
) t ON r.media_type = 'track' AND r.media_id = t.id
LEFT JOIN (
SELECT a.id, a.title, STRING_AGG(ar.name, ', ') AS artists, cover
FROM album a
JOIN album_artist aa on a.id = aa.album_id
JOIN artist ar ON aa.artist_id = ar.id
GROUP BY a.id, cover, a.title
) a ON r.media_type = 'album' AND r.media_id = a.id
LEFT JOIN review_tag rt ON r.id = rt.review_id
LEFT JOIN tag tag ON rt.tag_id = tag.id
LEFT JOIN (
SELECT post_id as review_id, COUNT(*) AS vote_count
FROM user_vote
WHERE post_type = 'review'
GROUP BY post_id
) v ON r.id = v.review_id
WHERE r.user_id = $1
GROUP BY r.id, r.user_id, u.username, u.display_name, u.profile_picture, r.media_type, r.media_id, r.rating, r.comment, r.created_at, r.updated_at, media_cover, media_title, media_artist, v.vote_count
`

if !rows.Next() {
return []*models.Review{}, nil
}
rows, err := r.Query(ctx, query, userId)

if err != nil {
return []*models.Review{}, err
fmt.Println(err)
return nil, err
}

defer rows.Close()

var reviews []*models.Review
for rows.Next() {
var review models.Review
var title sql.NullString
var previews []*models.Preview

if err := rows.Scan(
&review.ID,
&review.UserID,
&review.MediaID,
&review.MediaType,
&review.Rating,
// Scan results into the feedPosts slice
for rows.Next() {
var preview models.Preview
var title, comment sql.NullString // Use sql.NullString for nullable strings
err := rows.Scan(
&preview.ReviewID,
&preview.UserID,
&preview.Username,
&preview.DisplayName,
&preview.ProfilePicture,
&preview.MediaType,
&preview.MediaID,
&preview.Rating,
&title,
&review.Comment,
&review.CreatedAt,
&review.UpdatedAt,
&review.Draft,
); err != nil {
&comment,
&preview.CreatedAt,
&preview.UpdatedAt,
&preview.MediaCover,
&preview.MediaTitle,
&preview.MediaArtist,
&preview.Tags,
)
if err != nil {
fmt.Println(err)
return nil, err
}

// Assign comment to feedPost.Comment, handling null case
if comment.Valid {
preview.Comment = &comment.String // Point to the string if valid
} else {
preview.Comment = nil // Set to nil if null
}

if title.Valid {
review.Title = &title.String // Point to the string if valid
preview.Title = &title.String // Point to the string if valid
} else {
review.Title = nil // Set to nil if null
preview.Title = nil // Set to nil if null
}

// Ensure tags is an empty array if null
if preview.Tags == nil {
preview.Tags = []string{}
}

// Fetch review statistics for the current review
reviewStat, err := r.GetReviewStats(ctx, strconv.Itoa(preview.ReviewID))
if err != nil {
return nil, err
}

reviews = append(reviews, &review)
// If reviewStat is not nil, populate the corresponding fields in FeedPost
if reviewStat != nil {
preview.ReviewStat = *reviewStat
}

// Append the populated FeedPost to the feedPosts slice
previews = append(previews, &preview)
}

// Check for errors after looping through rows
if err := rows.Err(); err != nil {
return []*models.Review{}, err
return nil, err
}

return reviews, nil
return previews, nil
}

func (r *ReviewRepository) GetUserReviewOfTrack(ctx context.Context, mediaId string, userId string) (*models.Review, error) {
Expand Down
2 changes: 1 addition & 1 deletion backend/internal/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type UserRepository interface {

type ReviewRepository interface {
GetUserReviewsOfMedia(ctx context.Context, media_type string, mediaID string, userID string) ([]*models.Preview, error)
GetReviewsByUserID(ctx context.Context, id string) ([]*models.Review, error)
GetReviewsByUserID(ctx context.Context, id string) ([]*models.Preview, error)
CreateReview(ctx context.Context, review *models.Review) (*models.Review, error)
ReviewExists(ctx context.Context, id string) (bool, error)
UpdateReview(ctx context.Context, update *models.Review) (*models.Review, error)
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/(tabs)/profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export default function ProfileScreen() {
<View style={styles.topIconsContainer}>
{/* Activity icon with notification badge */}
<TouchableOpacity
onPress={handleActivityPress}
onPress={() => handleActivityPress(userId)}
style={styles.activityIconContainer}
>
<Icon name="activity" size={24} color="#000" />
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/(tabs)/user.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export default function ProfilePage() {
<View style={styles.header}>
<View style={styles.topIconsContainer}>
<TouchableOpacity
onPress={handleActivityPress}
onPress={() => handleActivityPress(userId)}
style={styles.activityIconContainer}
>
<Icon name="activity" size={24} color="#000" />
Expand Down
28 changes: 14 additions & 14 deletions frontend/app/Activity.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,19 @@ import {
SafeAreaView,
} from "react-native";
import Icon from "react-native-vector-icons/Ionicons";
import { router } from "expo-router";
import { router, useLocalSearchParams } from "expo-router";
import axios from "axios";
import ReviewCard from "@/components/ReviewCard";
import { useAuthContext } from "@/components/AuthProvider";
import ReviewPreview from "@/components/ReviewPreview";

const Activity = () => {
const BASE_URL = process.env.EXPO_PUBLIC_BASE_URL;
const [userReviews, setUserReviews] = useState<Review[]>();
const { userId } = useAuthContext();
const [userReviews, setUserReviews] = useState<Preview[]>();
const loggedInUser = useAuthContext().userId;
const { userId } = useLocalSearchParams<{
userId: string;
}>();

const handleDraftPress = () => {
console.log("Draft Button pressed");
Expand All @@ -27,7 +31,7 @@ const Activity = () => {
useEffect(() => {
const fetchUserReviews = async () => {
try {
const response = await axios.get(`${BASE_URL}/reviews/${userId}`);
const response = await axios.get(`${BASE_URL}/reviews/user/${userId}`);
setUserReviews(response.data);
} catch (error) {
console.error("Error fetching user reviews:", error);
Expand All @@ -53,20 +57,16 @@ const Activity = () => {
</SafeAreaView>

{/* Draft Button */}
<TouchableOpacity style={styles.draftButton} onPress={handleDraftPress}>
<Text style={styles.draftButtonText}>Drafts</Text>
</TouchableOpacity>
{loggedInUser === userId && (
<TouchableOpacity style={styles.draftButton} onPress={handleDraftPress}>
<Text style={styles.draftButtonText}>Drafts</Text>
</TouchableOpacity>
)}

{/* User Reviews Section */}
{userReviews && userReviews.length > 0 ? (
userReviews.map((review, index) => {
return (
<ReviewCard
key={index}
rating={review.rating}
comment={review.comment}
/>
);
return <ReviewPreview key={index} preview={review} />;
})
) : (
<Text style={styles.noReviewsText}>No reviews found.</Text>
Expand Down
28 changes: 15 additions & 13 deletions frontend/components/ReviewPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,16 @@ const ReviewPreview: React.FC<PreviewProps> = ({ preview }) => {
</View>

<TouchableOpacity onPress={handlePreviewPress}>
<Text style={styles.title}>{preview.title}</Text>
{preview.tags && preview.tags.length > 0 && (
<View style={styles.tagsContainer}>
{preview.tags.map((tag, index) => (
<View key={index} style={styles.tag}>
<Text style={styles.tagText}>{tag}</Text>
</View>
))}
</View>
)}
{preview.title && <Text style={styles.title}>{preview.title}</Text>}
{isEditable ? (
<View>
<TextInput
Expand Down Expand Up @@ -334,16 +343,6 @@ const ReviewPreview: React.FC<PreviewProps> = ({ preview }) => {
</Text>
</TouchableOpacity>
)}

{preview.tags && preview.tags.length > 0 && (
<View style={styles.tagsContainer}>
{preview.tags.map((tag, index) => (
<View key={index} style={styles.tag}>
<Text style={styles.tagText}>{tag}</Text>
</View>
))}
</View>
)}
</TouchableOpacity>
</View>

Expand Down Expand Up @@ -539,11 +538,13 @@ const styles = StyleSheet.create({
marginTop: 5,
width: 175,
textAlign: "left",
marginBottom: 5,
},
artistName: {
fontSize: 13,
color: "#666",
textAlign: "left",
marginBottom: 15,
},
ratingContainer: {
justifyContent: "flex-start",
Expand All @@ -557,6 +558,7 @@ const styles = StyleSheet.create({
},
title: {
fontWeight: 700,
marginTop: 10,
},
commentText: {
fontSize: 14,
Expand All @@ -571,11 +573,11 @@ const styles = StyleSheet.create({
tagsContainer: {
flexDirection: "row",
flexWrap: "wrap", // Allows wrapping to a new line
marginVertical: 8,
marginTop: 8,
gap: 8, // Space between tags
},
tag: {
backgroundColor: "rgba(242, 128, 55, 0.65)",
backgroundColor: "#FDE1D5",
paddingVertical: 5,
paddingHorizontal: 12,
borderRadius: 20,
Expand Down
7 changes: 5 additions & 2 deletions frontend/hooks/useProfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,11 @@ export function useProfile(userId: string) {
}
}, [userId]);

const handleActivityPress = () => {
router.push("/Activity");
const handleActivityPress = (userId: string) => {
router.push({
pathname: "/Activity",
params: { userId: userId },
});
};

const handleOnQueuePress = () => {
Expand Down

0 comments on commit df3e235

Please sign in to comment.