diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 95385ad42..c0bf059c3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -53,8 +53,8 @@ cd OpenIsle --profile dev up -d ``` 该命令会创建名为 `frontend_dev` 的容器并运行 `npm run dev`,浏览器访问 http://127.0.0.1:3000 即可查看页面。 - - 修改代码后,可以强制重新创建所有容器,执行: + 修改前端代码,页面会热更新。 + 如果修改后端代码,可以重启后端容器, 或是环境变量中指向IDEA,采用IDEA编译运行也可以哦。 ```shell docker compose \ diff --git a/backend/src/main/java/com/openisle/controller/PostDonationController.java b/backend/src/main/java/com/openisle/controller/PostDonationController.java new file mode 100644 index 000000000..b74239416 --- /dev/null +++ b/backend/src/main/java/com/openisle/controller/PostDonationController.java @@ -0,0 +1,43 @@ +package com.openisle.controller; + +import com.openisle.dto.DonationRequest; +import com.openisle.dto.DonationResponse; +import com.openisle.service.PointService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/posts/{postId}/donations") +@RequiredArgsConstructor +public class PostDonationController { + + private final PointService pointService; + + @GetMapping + @Operation(summary = "List donations", description = "Get recent donations for a post") + @ApiResponse(responseCode = "200", description = "Donation summary") + public DonationResponse list(@PathVariable Long postId) { + return pointService.getPostDonations(postId); + } + + @PostMapping + @SecurityRequirement(name = "JWT") + @Operation(summary = "Donate", description = "Donate points to the post author") + @ApiResponse(responseCode = "200", description = "Donation result") + public DonationResponse donate( + @PathVariable Long postId, + @RequestBody DonationRequest req, + Authentication auth + ) { + return pointService.donateToPost(auth.getName(), postId, req.getAmount()); + } +} diff --git a/backend/src/main/java/com/openisle/dto/DonationDto.java b/backend/src/main/java/com/openisle/dto/DonationDto.java new file mode 100644 index 000000000..460cec56b --- /dev/null +++ b/backend/src/main/java/com/openisle/dto/DonationDto.java @@ -0,0 +1,16 @@ +package com.openisle.dto; + +import java.time.LocalDateTime; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class DonationDto { + + private Long userId; + private String username; + private String avatar; + private int amount; + private LocalDateTime createdAt; +} diff --git a/backend/src/main/java/com/openisle/dto/DonationRequest.java b/backend/src/main/java/com/openisle/dto/DonationRequest.java new file mode 100644 index 000000000..14421e1e5 --- /dev/null +++ b/backend/src/main/java/com/openisle/dto/DonationRequest.java @@ -0,0 +1,11 @@ +package com.openisle.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class DonationRequest { + + private int amount; +} diff --git a/backend/src/main/java/com/openisle/dto/DonationResponse.java b/backend/src/main/java/com/openisle/dto/DonationResponse.java new file mode 100644 index 000000000..1a83be807 --- /dev/null +++ b/backend/src/main/java/com/openisle/dto/DonationResponse.java @@ -0,0 +1,15 @@ +package com.openisle.dto; + +import java.util.ArrayList; +import java.util.List; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class DonationResponse { + + private int totalAmount; + private List donations = new ArrayList<>(); + private Integer balance; +} diff --git a/backend/src/main/java/com/openisle/dto/PostChangeLogDto.java b/backend/src/main/java/com/openisle/dto/PostChangeLogDto.java index ce5d55201..296287f0a 100644 --- a/backend/src/main/java/com/openisle/dto/PostChangeLogDto.java +++ b/backend/src/main/java/com/openisle/dto/PostChangeLogDto.java @@ -29,4 +29,5 @@ public class PostChangeLogDto { private LocalDateTime newPinnedAt; private Boolean oldFeatured; private Boolean newFeatured; + private Integer amount; } diff --git a/backend/src/main/java/com/openisle/mapper/PostChangeLogMapper.java b/backend/src/main/java/com/openisle/mapper/PostChangeLogMapper.java index 52611c5d7..cb0d1a9f1 100644 --- a/backend/src/main/java/com/openisle/mapper/PostChangeLogMapper.java +++ b/backend/src/main/java/com/openisle/mapper/PostChangeLogMapper.java @@ -52,6 +52,8 @@ public class PostChangeLogMapper { } else if (log instanceof PostFeaturedChangeLog f) { dto.setOldFeatured(f.isOldFeatured()); dto.setNewFeatured(f.isNewFeatured()); + } else if (log instanceof PostDonateChangeLog d) { + dto.setAmount(d.getAmount()); } return dto; } diff --git a/backend/src/main/java/com/openisle/model/NotificationType.java b/backend/src/main/java/com/openisle/model/NotificationType.java index 0e96cfc20..74262c9b2 100644 --- a/backend/src/main/java/com/openisle/model/NotificationType.java +++ b/backend/src/main/java/com/openisle/model/NotificationType.java @@ -48,6 +48,8 @@ public enum NotificationType { POLL_RESULT_PARTICIPANT, /** Your post was featured */ POST_FEATURED, + /** Someone donated to your post */ + DONATION, /** You were mentioned in a post or comment */ MENTION, } diff --git a/backend/src/main/java/com/openisle/model/PointHistoryType.java b/backend/src/main/java/com/openisle/model/PointHistoryType.java index 689f73c9c..776827f0a 100644 --- a/backend/src/main/java/com/openisle/model/PointHistoryType.java +++ b/backend/src/main/java/com/openisle/model/PointHistoryType.java @@ -13,4 +13,6 @@ public enum PointHistoryType { REDEEM, LOTTERY_JOIN, LOTTERY_REWARD, + DONATE_SENT, + DONATE_RECEIVED, } diff --git a/backend/src/main/java/com/openisle/model/PostChangeType.java b/backend/src/main/java/com/openisle/model/PostChangeType.java index c09a5555a..eeee99cbb 100644 --- a/backend/src/main/java/com/openisle/model/PostChangeType.java +++ b/backend/src/main/java/com/openisle/model/PostChangeType.java @@ -10,4 +10,5 @@ public enum PostChangeType { FEATURED, VOTE_RESULT, LOTTERY_RESULT, + DONATE, } diff --git a/backend/src/main/java/com/openisle/model/PostDonateChangeLog.java b/backend/src/main/java/com/openisle/model/PostDonateChangeLog.java new file mode 100644 index 000000000..50eed96eb --- /dev/null +++ b/backend/src/main/java/com/openisle/model/PostDonateChangeLog.java @@ -0,0 +1,19 @@ +package com.openisle.model; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@Entity +@Table(name = "post_donate_change_logs") +public class PostDonateChangeLog extends PostChangeLog { + + @Column(nullable = false) + private int amount; +} diff --git a/backend/src/main/java/com/openisle/repository/PointHistoryRepository.java b/backend/src/main/java/com/openisle/repository/PointHistoryRepository.java index 197ac1a45..3436466a3 100644 --- a/backend/src/main/java/com/openisle/repository/PointHistoryRepository.java +++ b/backend/src/main/java/com/openisle/repository/PointHistoryRepository.java @@ -2,11 +2,14 @@ package com.openisle.repository; import com.openisle.model.Comment; import com.openisle.model.PointHistory; +import com.openisle.model.PointHistoryType; import com.openisle.model.Post; import com.openisle.model.User; import java.time.LocalDateTime; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; public interface PointHistoryRepository extends JpaRepository { List findByUserOrderByIdDesc(User user); @@ -21,4 +24,11 @@ public interface PointHistoryRepository extends JpaRepository findByComment(Comment comment); List findByPost(Post post); + + List findTop10ByPostAndTypeOrderByCreatedAtDesc(Post post, PointHistoryType type); + + @Query( + "SELECT COALESCE(SUM(ph.amount), 0) FROM PointHistory ph WHERE ph.post = :post AND ph.type = :type" + ) + Long sumAmountByPostAndType(@Param("post") Post post, @Param("type") PointHistoryType type); } diff --git a/backend/src/main/java/com/openisle/service/PointService.java b/backend/src/main/java/com/openisle/service/PointService.java index 0a8349a53..7b4af0f96 100644 --- a/backend/src/main/java/com/openisle/service/PointService.java +++ b/backend/src/main/java/com/openisle/service/PointService.java @@ -1,5 +1,7 @@ package com.openisle.service; +import com.openisle.dto.DonationDto; +import com.openisle.dto.DonationResponse; import com.openisle.exception.FieldException; import com.openisle.model.*; import com.openisle.repository.*; @@ -8,8 +10,10 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor @@ -20,6 +24,8 @@ public class PointService { private final PostRepository postRepository; private final CommentRepository commentRepository; private final PointHistoryRepository pointHistoryRepository; + private final NotificationService notificationService; + private final PostChangeLogService postChangeLogService; public int awardForPost(String userName, Long postId) { User user = userRepository.findByUsername(userName).orElseThrow(); @@ -272,4 +278,95 @@ public class PointService { User user = userRepository.findByUsername(userName).orElseThrow(); return recalculateUserPoints(user); } + + @Transactional + public DonationResponse donateToPost(String donorName, Long postId, int amount) { + if (amount <= 0) { + throw new FieldException("amount", "打赏积分必须大于0"); + } + User donor = userRepository.findByUsername(donorName).orElseThrow(); + Post post = postRepository.findById(postId).orElseThrow(); + User author = post.getAuthor(); + if (author.getId().equals(donor.getId())) { + throw new FieldException("post", "不能给自己打赏"); + } + if (donor.getPoint() < amount) { + throw new FieldException("point", "积分不足"); + } + addPoint(donor, -amount, PointHistoryType.DONATE_SENT, post, null, author); + addPoint(author, amount, PointHistoryType.DONATE_RECEIVED, post, null, donor); + notificationService.createNotification( + author, + NotificationType.DONATION, + post, + null, + null, + donor, + null, + String.valueOf(amount) + ); + postChangeLogService.recordDonation(post, donor, amount); + DonationResponse response = buildDonationResponse(post); + response.setBalance(donor.getPoint()); + return response; + } + + public DonationResponse getPostDonations(Long postId) { + Post post = postRepository.findById(postId).orElseThrow(); + return buildDonationResponse(post); + } + + private DonationResponse buildDonationResponse(Post post) { + List histories = + pointHistoryRepository.findTop10ByPostAndTypeOrderByCreatedAtDesc( + post, + PointHistoryType.DONATE_RECEIVED + ); + List donations = histories + .stream() + .collect(Collectors.collectingAndThen(Collectors.toMap( + history -> { + User donor = history.getFromUser(); + if (donor != null && donor.getId() != null) { + return "user:" + donor.getId(); + } + return "history:" + history.getId(); + }, + history -> { + DonationDto dto = new DonationDto(); + User donor = history.getFromUser(); + if (donor != null) { + dto.setUserId(donor.getId()); + dto.setUsername(donor.getUsername()); + dto.setAvatar(donor.getAvatar()); + } + dto.setAmount(history.getAmount()); + dto.setCreatedAt(history.getCreatedAt()); + return dto; + }, + (left, right) -> { + left.setAmount(left.getAmount() + right.getAmount()); + if ( + left.getCreatedAt() == null || + (right.getCreatedAt() != null && right.getCreatedAt().isAfter(left.getCreatedAt())) + ) { + left.setCreatedAt(right.getCreatedAt()); + } + return left; + }, + java.util.LinkedHashMap::new + ), map -> new java.util.ArrayList<>(map.values()))); + Long total = pointHistoryRepository.sumAmountByPostAndType( + post, + PointHistoryType.DONATE_RECEIVED + ); + int safeTotal = 0; + if (total != null) { + safeTotal = total > Integer.MAX_VALUE ? Integer.MAX_VALUE : total.intValue(); + } + DonationResponse response = new DonationResponse(); + response.setDonations(donations); + response.setTotalAmount(safeTotal); + return response; + } } diff --git a/backend/src/main/java/com/openisle/service/PostChangeLogService.java b/backend/src/main/java/com/openisle/service/PostChangeLogService.java index df78a266d..0d3fd28ad 100644 --- a/backend/src/main/java/com/openisle/service/PostChangeLogService.java +++ b/backend/src/main/java/com/openisle/service/PostChangeLogService.java @@ -115,6 +115,15 @@ public class PostChangeLogService { logRepository.save(log); } + public void recordDonation(Post post, User donor, int amount) { + PostDonateChangeLog log = new PostDonateChangeLog(); + log.setPost(post); + log.setUser(donor); + log.setType(PostChangeType.DONATE); + log.setAmount(amount); + logRepository.save(log); + } + public void deleteLogsForPost(Post post) { logRepository.deleteByPost(post); } diff --git a/frontend_nuxt/assets/global.css b/frontend_nuxt/assets/global.css index 4db59267d..05302372a 100644 --- a/frontend_nuxt/assets/global.css +++ b/frontend_nuxt/assets/global.css @@ -3,7 +3,7 @@ --primary-color: rgb(10, 110, 120); --primary-color-disabled: rgba(93, 152, 156, 0.5); --secondary-color: rgb(255, 255, 255); - --secondary-color-hover: rgba(10, 111, 120, 0.184); + --secondary-color-hover: rgba(10, 111, 120, 0.079); --new-post-icon-color: rgba(10, 111, 120, 0.598); --header-height: 60px; --header-background-color: white; @@ -54,6 +54,7 @@ --header-border-color: #555; --primary-color: rgb(17, 182, 197); --primary-color-hover: rgb(13, 137, 151); + --secondary-color-hover: rgba(17, 182, 197, 0.238); --new-post-icon-color: rgba(10, 111, 120, 0.598); --header-text-color: white; --app-menu-background-color: #333; @@ -179,7 +180,7 @@ body { .info-content-text pre .line-numbers { counter-reset: line-number 0; - white-space: nowrap; /* 禁止数字换行 */ + white-space: nowrap; /* 禁止数字换行 */ font-variant-numeric: tabular-nums; /* 数字等宽 */ /* width: 2em; */ font-size: 13px; @@ -343,7 +344,7 @@ body { .info-content-text pre { line-height: 1.5; } - + /*处理iframe视频标签*/ .info-content-text iframe { width: 100%; diff --git a/frontend_nuxt/components/BaseItemGroup.vue b/frontend_nuxt/components/BaseItemGroup.vue new file mode 100644 index 000000000..af6e127da --- /dev/null +++ b/frontend_nuxt/components/BaseItemGroup.vue @@ -0,0 +1,187 @@ + + + + + diff --git a/frontend_nuxt/components/BaseUserAvatar.vue b/frontend_nuxt/components/BaseUserAvatar.vue index 6e0b62ab5..cb7c61617 100644 --- a/frontend_nuxt/components/BaseUserAvatar.vue +++ b/frontend_nuxt/components/BaseUserAvatar.vue @@ -15,7 +15,7 @@ import { computed, ref, watch } from 'vue' import { useAttrs } from 'vue' import BaseImage from './BaseImage.vue' -const DEFAULT_AVATAR = '/default-avatar.svg' +const DEFAULT_AVATAR = '/default-avatar.jpg' const props = defineProps({ userId: { @@ -109,7 +109,7 @@ function onError() { } .base-user-avatar:hover { - box-shadow: 0 4px 24px rgba(0, 0, 0, 0.1); + box-shadow: 0 4px 24px rgba(251, 138, 138, 0.1); transform: scale(1.05); } diff --git a/frontend_nuxt/components/CommentItem.vue b/frontend_nuxt/components/CommentItem.vue index b47456dda..34a7e703d 100644 --- a/frontend_nuxt/components/CommentItem.vue +++ b/frontend_nuxt/components/CommentItem.vue @@ -53,14 +53,29 @@ @click="handleContentClick" > - -
写个回复...
-
+
+ +
+ +
+ 写个回复... +
+
+
@@ -180,6 +197,32 @@ function setReply(message) { replyTo.value = message } +const messageReactionRefs = new Map() +function setMessageReactionRef(id, el) { + if (el) { + messageReactionRefs.set(id, el) + } else { + messageReactionRefs.delete(id) + } +} + +function getMessageLikeCount(message) { + return (message.reactions || []).filter((reaction) => reaction.type === 'LIKE').length +} + +function isMessageLiked(message) { + const username = currentUser.value?.username + if (!username) return false + return (message.reactions || []).some( + (reaction) => reaction.type === 'LIKE' && reaction.user === username, + ) +} + +function toggleMessageLike(message) { + const group = messageReactionRefs.get(message.id) + group?.toggleReaction('LIKE') +} + /** 改造:滚动函数 —— smooth & instant */ function scrollToBottomSmooth() { const el = messagesListEl.value @@ -710,6 +753,55 @@ function goBack() { background-color: var(--normal-light-background-color); } +.message-reaction-row { + display: flex; + flex-direction: row; + justify-content: space-between; + gap: 10px; + flex-wrap: wrap; + margin-top: 6px; +} + +.message-reaction-actions { + display: flex; + flex-direction: row; + align-items: center; + gap: 10px; +} + +.reaction-action { + cursor: pointer; + padding: 4px 10px; + border-radius: 10px; + display: flex; + align-items: center; + gap: 5px; + opacity: 0.6; + font-size: 16px; + transition: + background-color 0.2s ease, + opacity 0.2s ease; +} + +.reaction-action:hover { + opacity: 1; + background-color: var(--normal-light-background-color); +} + +.reaction-action.like-action { + color: #ff0000; +} + +.reaction-action.selected { + opacity: 1; + background-color: var(--normal-light-background-color); +} + +.reaction-count { + font-size: 14px; + font-weight: bold; +} + .reply-header { display: flex; flex-direction: row; @@ -723,14 +815,8 @@ function goBack() { } .reply-btn { - cursor: pointer; - padding: 4px; - opacity: 0.6; font-size: 12px; -} - -.reply-btn:hover { - opacity: 1; + color: var(--primary-color); } .active-reply { diff --git a/frontend_nuxt/pages/message-box/index.vue b/frontend_nuxt/pages/message-box/index.vue index 75b30406d..8b384352e 100644 --- a/frontend_nuxt/pages/message-box/index.vue +++ b/frontend_nuxt/pages/message-box/index.vue @@ -84,7 +84,7 @@ >
+ + + 你目前的积分是 {{ item.balance }}
@@ -248,6 +269,8 @@ const iconMap = { FEATURE: 'star', LOTTERY_JOIN: 'medal-one', LOTTERY_REWARD: 'fireworks', + DONATE_SENT: 'paper-money-two', + DONATE_RECEIVED: 'paper-money-two', POST_LIKE_CANCELLED: 'clear-icon', COMMENT_LIKE_CANCELLED: 'clear-icon', } diff --git a/frontend_nuxt/pages/posts/[id]/index.vue b/frontend_nuxt/pages/posts/[id]/index.vue index 8fd467b82..5ed2eae94 100644 --- a/frontend_nuxt/pages/posts/[id]/index.vue +++ b/frontend_nuxt/pages/posts/[id]/index.vue @@ -92,11 +92,29 @@ >
@@ -196,6 +214,7 @@ import PostChangeLogItem from '~/components/PostChangeLogItem.vue' import ArticleTags from '~/components/ArticleTags.vue' import ArticleCategory from '~/components/ArticleCategory.vue' import ReactionsGroup from '~/components/ReactionsGroup.vue' +import DonateGroup from '~/components/DonateGroup.vue' import DropdownMenu from '~/components/DropdownMenu.vue' import PostLottery from '~/components/PostLottery.vue' import PostPoll from '~/components/PostPoll.vue' @@ -223,6 +242,18 @@ const postContent = ref('') const category = ref('') const tags = ref([]) const postReactions = ref([]) +const postReactionsGroupRef = ref(null) +const postLikeCount = computed( + () => postReactions.value.filter((reaction) => reaction.type === 'LIKE').length, +) +const postLikedByMe = computed(() => + postReactions.value.some( + (reaction) => reaction.type === 'LIKE' && reaction.user === authState.username, + ), +) +const togglePostLike = () => { + postReactionsGroupRef.value?.toggleReaction('LIKE') +} const comments = ref([]) const changeLogs = ref([]) const status = ref('PUBLISHED') @@ -366,9 +397,9 @@ const changeLogIcon = (l) => { return 'unlock' } } else if (l.type === 'PINNED') { - if(l.newPinnedAt){ + if (l.newPinnedAt) { return 'pin' - }else{ + } else { return 'clear-icon' } } else if (l.type === 'FEATURED') { @@ -381,6 +412,8 @@ const changeLogIcon = (l) => { return 'check-one' } else if (l.type === 'LOTTERY_RESULT') { return 'gift' + } else if (l.type === 'DONATE') { + return 'financing' } else { return 'info' } @@ -405,6 +438,7 @@ const mapChangeLog = (l) => ({ newCategory: l.newCategory, oldTags: l.oldTags, newTags: l.newTags, + amount: l.amount, icon: changeLogIcon(l), }) @@ -1245,35 +1279,61 @@ onMounted(async () => { .article-footer-container { display: flex; flex-direction: row; + justify-content: space-between; gap: 10px; margin-top: 0px; + flex-wrap: wrap; + margin-bottom: 10px; } -.reactions-viewer { +.option-container { display: flex; flex-direction: row; - gap: 20px; align-items: center; + flex-wrap: wrap; } -.reactions-viewer-item-container { - display: flex; - flex-direction: row; - gap: 2px; - align-items: center; -} - -.reactions-viewer-item { - font-size: 16px; -} - -.make-reaction-container { +.article-footer-actions { display: flex; flex-direction: row; gap: 10px; + align-items: center; } -.copy-link:hover { +.reaction-action { + cursor: pointer; + padding: 4px 10px; + opacity: 0.6; + border-radius: 10px; + font-size: 20px; + display: flex; + align-items: center; + gap: 5px; + transition: + background-color 0.2s ease, + opacity 0.2s ease; +} + +.reaction-action:hover { + opacity: 1; + background-color: var(--normal-light-background-color); +} + +.reaction-action.like-action { + color: #ff0000; +} + +.reaction-action.selected { + opacity: 1; + background-color: var(--normal-light-background-color); +} + +.reaction-count { + font-size: 16px; + font-weight: bold; +} + +.reaction-action.copy-link:hover { background-color: #e2e2e2; } diff --git a/frontend_nuxt/plugins/iconpark.client.ts b/frontend_nuxt/plugins/iconpark.client.ts index d0ab502d9..58338d98a 100644 --- a/frontend_nuxt/plugins/iconpark.client.ts +++ b/frontend_nuxt/plugins/iconpark.client.ts @@ -80,6 +80,7 @@ import { Dislike, CheckOne, Share, + Financing, } from '@icon-park/vue-next' export default defineNuxtPlugin((nuxtApp) => { @@ -163,4 +164,5 @@ export default defineNuxtPlugin((nuxtApp) => { nuxtApp.vueApp.component('Dislike', Dislike) nuxtApp.vueApp.component('CheckOne', CheckOne) nuxtApp.vueApp.component('Share', Share) + nuxtApp.vueApp.component('Financing', Financing) }) diff --git a/frontend_nuxt/public/default-avatar.jpg b/frontend_nuxt/public/default-avatar.jpg new file mode 100644 index 000000000..402804fce Binary files /dev/null and b/frontend_nuxt/public/default-avatar.jpg differ diff --git a/frontend_nuxt/public/default-avatar.svg b/frontend_nuxt/public/default-avatar.svg deleted file mode 100644 index 5b773a4ca..000000000 --- a/frontend_nuxt/public/default-avatar.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend_nuxt/utils/notification.js b/frontend_nuxt/utils/notification.js index d05875cb9..9d71e2a54 100644 --- a/frontend_nuxt/utils/notification.js +++ b/frontend_nuxt/utils/notification.js @@ -31,6 +31,7 @@ const iconMap = { MENTION: 'HashtagKey', POST_DELETED: 'ClearIcon', POST_FEATURED: 'Star', + DONATION: 'PaperMoneyTwo', } export async function fetchUnreadCount() { @@ -334,6 +335,18 @@ function createFetchNotifications() { } }, }) + } else if (n.type === 'DONATION') { + arr.push({ + ...n, + src: n.fromUser ? n.fromUser.avatar : null, + icon: n.fromUser ? undefined : iconMap[n.type], + iconClick: () => { + if (n.post) { + markNotificationRead(n.id) + navigateTo(`/posts/${n.post.id}`, { replace: true }) + } + }, + }) } else if (n.type === 'REGISTER_REQUEST') { arr.push({ ...n,