feat(pages): create user profile page
This commit is contained in:
		
							parent
							
								
									8a042ec028
								
							
						
					
					
						commit
						a5ca37b4b7
					
				
							
								
								
									
										228
									
								
								pages/user/[id].vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										228
									
								
								pages/user/[id].vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,228 @@ | |||||||
|  | <script lang="ts" setup> | ||||||
|  | 	import { format, formatDistanceToNow, formatRelative } from "date-fns"; | ||||||
|  | 	import { IUser } from "~/models/user"; | ||||||
|  | 	import { IStory } from "~/models/stories"; | ||||||
|  | 	import { favourites } from "~/lib/client/listActions"; | ||||||
|  | 	import singleStory from "~/components/listings/singleStory.vue"; | ||||||
|  | 	import icon from "~/components/icon.vue"; | ||||||
|  | 	import adminPanel from "~/components/profile/adminPanel.vue"; | ||||||
|  | 
 | ||||||
|  | 	const rtr = useRoute(); | ||||||
|  | 	const { data } = useAuth(); | ||||||
|  | 
 | ||||||
|  | 	const { data: userInfo } = await useApiFetch<IUser>(`/user/${rtr.params.id}`); | ||||||
|  | 	if (userInfo === null) { | ||||||
|  | 		navigateTo("/"); | ||||||
|  | 	} | ||||||
|  | 	const activeKey = ref("main"); | ||||||
|  | 	const activeFavKey = ref("favs/stories"); | ||||||
|  | 	const uLastVisit = Date.parse( | ||||||
|  | 		(userInfo.value?.lastVisit || | ||||||
|  | 			userInfo.value?.lastLogin) as unknown as string, | ||||||
|  | 	); | ||||||
|  | 
 | ||||||
|  | 	const isSelf = userInfo.value?._id === parseInt(rtr.params.id as string); | ||||||
|  | 
 | ||||||
|  | 	console.log("rtr", rtr); | ||||||
|  | 	console.log("LVLVLVLVVLV", new Date(uLastVisit)); | ||||||
|  | </script> | ||||||
|  | <template> | ||||||
|  | 	<a-card style="width: 100%"> | ||||||
|  | 		<template #title> | ||||||
|  | 			<div style="height: fit-content"> | ||||||
|  | 				<a-card-meta style="align-items: center; margin: 0.5em"> | ||||||
|  | 					<template #avatar> | ||||||
|  | 						<a-avatar | ||||||
|  | 							:size="75" | ||||||
|  | 							:src="`/avatars/${userInfo?.profile.avatar}.png`" | ||||||
|  | 						/> | ||||||
|  | 					</template> | ||||||
|  | 					<template #title> | ||||||
|  | 						<a-typography-title :level="1" style="margin-top: 0.5em"> | ||||||
|  | 							{{ userInfo!.username }} | ||||||
|  | 						</a-typography-title> | ||||||
|  | 					</template> | ||||||
|  | 				</a-card-meta> | ||||||
|  | 			</div> | ||||||
|  | 			<a-badge-ribbon color="#d03f5b" v-if="userInfo?.profile.isAdmin"> | ||||||
|  | 				<template #text> Administrator </template> | ||||||
|  | 			</a-badge-ribbon> | ||||||
|  | 		</template> | ||||||
|  | 		<a-descriptions | ||||||
|  | 			:column="2" | ||||||
|  | 			:labelStyle="{ fontWeight: 'bold' }" | ||||||
|  | 			:colon="false" | ||||||
|  | 		> | ||||||
|  | 			<a-descriptions-item label="Last visit"> | ||||||
|  | 				<div v-if="userInfo?.banned" style="color: red; font-weight: bold"> | ||||||
|  | 					BANNED | ||||||
|  | 				</div> | ||||||
|  | 				<div v-else-if="userInfo?.profile.hidden"> | ||||||
|  | 					<i>Unknown</i> | ||||||
|  | 				</div> | ||||||
|  | 				<div v-else> | ||||||
|  | 					<span> | ||||||
|  | 						{{ format(uLastVisit, "MM/dd/yyyy @ hh:mm:ss a") }} | ||||||
|  | 					</span> | ||||||
|  | 					<span style="margin-left: 0.6em"> | ||||||
|  | 						({{ formatDistanceToNow(uLastVisit, { addSuffix: true }) }}) | ||||||
|  | 					</span> | ||||||
|  | 				</div> | ||||||
|  | 			</a-descriptions-item> | ||||||
|  | 			<a-descriptions-item label="Website"> | ||||||
|  | 				<a | ||||||
|  | 					target="_blank" | ||||||
|  | 					:href="`${ | ||||||
|  | 						userInfo?.profile.website.startsWith('http') ? '' : 'http://' | ||||||
|  | 					}${userInfo?.profile.website}`" | ||||||
|  | 				> | ||||||
|  | 					{{ userInfo?.profile.website }} | ||||||
|  | 				</a> | ||||||
|  | 			</a-descriptions-item> | ||||||
|  | 			<a-descriptions-item label="Blog/Journal"> | ||||||
|  | 				<a | ||||||
|  | 					target="_blank" | ||||||
|  | 					:href="`${ | ||||||
|  | 						userInfo?.profile.blog.startsWith('http') ? '' : 'http://' | ||||||
|  | 					}${userInfo?.profile.blog}`" | ||||||
|  | 				> | ||||||
|  | 					{{ userInfo?.profile.blog }} | ||||||
|  | 				</a> | ||||||
|  | 			</a-descriptions-item> | ||||||
|  | 			<a-descriptions-item label="Occupation"> | ||||||
|  | 				{{ userInfo?.profile.occupation }} | ||||||
|  | 			</a-descriptions-item> | ||||||
|  | 			<a-descriptions-item | ||||||
|  | 				label="Email" | ||||||
|  | 				v-if="userInfo?.profile.showEmail || data?.user?.profile.isAdmin" | ||||||
|  | 			> | ||||||
|  | 				{{ userInfo?.email }} | ||||||
|  | 			</a-descriptions-item> | ||||||
|  | 		</a-descriptions> | ||||||
|  | 		<a-divider style="border: 1px solid #3e1560" /> | ||||||
|  | 		<a-tabs centered v-model:active-key="activeKey"> | ||||||
|  | 			<a-tab-pane key="main" tab="Profile"> | ||||||
|  | 				<div v-html="userInfo?.profile.bio"></div> | ||||||
|  | 			</a-tab-pane> | ||||||
|  | 			<a-tab-pane key="stories" tab="Stories"> | ||||||
|  | 				<listings-stories :prefix="`/user/${$route.params.id}/stories`" /> | ||||||
|  | 			</a-tab-pane> | ||||||
|  | 			<a-tab-pane key="favs" tab="Favourites"> | ||||||
|  | 				<a-tabs centered v-model:active-key="activeFavKey"> | ||||||
|  | 					<a-tab-pane key="favs/stories" tab="Stories"> | ||||||
|  | 						<a-list | ||||||
|  | 							:pagination="{ | ||||||
|  | 								defaultPageSize: 20, | ||||||
|  | 								total: userInfo?.favs.stories.length, | ||||||
|  | 								defaultCurrent: 1, | ||||||
|  | 								// onChange: pagiChange, | ||||||
|  | 								hideOnSinglePage: true, | ||||||
|  | 								showSizeChanger: false, | ||||||
|  | 							}" | ||||||
|  | 							:data-source="userInfo?.favs.stories" | ||||||
|  | 							item-layout="vertical" | ||||||
|  | 						> | ||||||
|  | 							<template #renderItem="{ item }"> | ||||||
|  | 								<!-- {{ item.title }} --> | ||||||
|  | 								<a-row :gutter="[25, 0]" :align="'middle'"> | ||||||
|  | 									<a-col :span="23"> | ||||||
|  | 										<single-story :story="item" /> | ||||||
|  | 									</a-col> | ||||||
|  | 									<a-col :span="1" v-if="isSelf"> | ||||||
|  | 										<a | ||||||
|  | 											style="color: red" | ||||||
|  | 											@click=" | ||||||
|  | 												() => | ||||||
|  | 													favourites( | ||||||
|  | 														userInfo?.favs.stories || [], | ||||||
|  | 														item._id, | ||||||
|  | 														true, | ||||||
|  | 														'story', | ||||||
|  | 													) | ||||||
|  | 											" | ||||||
|  | 										> | ||||||
|  | 											<icon istyle="regular" name="trash" color="#f00" /> | ||||||
|  | 										</a> | ||||||
|  | 									</a-col> | ||||||
|  | 								</a-row> | ||||||
|  | 							</template> | ||||||
|  | 						</a-list> | ||||||
|  | 					</a-tab-pane> | ||||||
|  | 					<a-tab-pane key="favs/authors" tab="Authors"> | ||||||
|  | 						<a-list | ||||||
|  | 							item-layout="horizontal" | ||||||
|  | 							:data-source="userInfo?.favs.authors" | ||||||
|  | 							:grid="{ gutter: 16, column: 3 }" | ||||||
|  | 						> | ||||||
|  | 							<template #renderItem="{ item }"> | ||||||
|  | 								<a-list-item style="display: flex; align-items: center"> | ||||||
|  | 									<a-list-item-meta | ||||||
|  | 										style="align-items: center; width: min-content" | ||||||
|  | 									> | ||||||
|  | 										<template #avatar> | ||||||
|  | 											<a-avatar :src="`/avatars/${item.profile.avatar}.png`" /> | ||||||
|  | 										</template> | ||||||
|  | 										<template #title :style="{ background: 'pink' }"> | ||||||
|  | 											<nuxt-link :to="`/user/${item._id}`"> | ||||||
|  | 												{{ item.username }} | ||||||
|  | 											</nuxt-link> | ||||||
|  | 										</template> | ||||||
|  | 									</a-list-item-meta> | ||||||
|  | 									<template #actions v-if="isSelf"> | ||||||
|  | 										<span> | ||||||
|  | 											<a | ||||||
|  | 												style="color: red" | ||||||
|  | 												@click=" | ||||||
|  | 													() => | ||||||
|  | 														favourites( | ||||||
|  | 															userInfo?.favs.authors || [], | ||||||
|  | 															item._id, | ||||||
|  | 															true, | ||||||
|  | 															'author', | ||||||
|  | 														) | ||||||
|  | 												" | ||||||
|  | 											> | ||||||
|  | 												<icon istyle="regular" name="trash" color="#f00" /> | ||||||
|  | 											</a> | ||||||
|  | 										</span> | ||||||
|  | 									</template> | ||||||
|  | 								</a-list-item> | ||||||
|  | 							</template> | ||||||
|  | 						</a-list> | ||||||
|  | 					</a-tab-pane> | ||||||
|  | 				</a-tabs> | ||||||
|  | 			</a-tab-pane> | ||||||
|  | 			<a-tab-pane key="admin" tab="Admin" v-if="data?.user?.profile.isAdmin"> | ||||||
|  | 				<admin-panel :user="userInfo" /> | ||||||
|  | 			</a-tab-pane> | ||||||
|  | 		</a-tabs> | ||||||
|  | 	</a-card> | ||||||
|  | </template> | ||||||
|  | <style> | ||||||
|  | 	.ant-list-item-action { | ||||||
|  | 		width: min-content; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	.ant-ribbon-wrapper { | ||||||
|  | 		position: unset !important; | ||||||
|  | 		zoom: 200%; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	.ant-list-item-meta-title { | ||||||
|  | 		margin-top: 0.1em; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	.ant-card-head-title, | ||||||
|  | 	.ant-card-head { | ||||||
|  | 		height: 110% !important; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	.ant-list-item-meta-content { | ||||||
|  | 		align-self: center !important; | ||||||
|  | 	} | ||||||
|  | </style> | ||||||
|  | <style scoped> | ||||||
|  | 	.ant-list-items > * + * { | ||||||
|  | 		margin-top: 1.2em; | ||||||
|  | 	} | ||||||
|  | </style> | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user