minhnt-dev: make UI

This commit is contained in:
MoreStrive
2024-05-30 21:32:51 +07:00
parent 2aa5607c48
commit b52352660d
16 changed files with 315 additions and 169 deletions
+3
View File
@@ -0,0 +1,3 @@
import { twMerge } from "tailwind-merge";
import { clsx, ClassValue } from "clsx";
export default (...inputs: ClassValue[]) => twMerge(clsx(inputs));
+105
View File
@@ -0,0 +1,105 @@
import useStorage from '~/composables/useStorage'
type ArticleReading = {
articleId: number
readingDuration: number
}
type UserReadingHabits = {
accessSpecificSections: number[]
accessSpecificArticles: number[]
articleReadingDuration:ArticleReading[]
readingDuration:number
readAndParticipateInDiscussions: number[]
useSearchTools: string[]
}
export default (entity?: any) => {
const { get, set } = useStorage()
let startTime = Date.now()
const getReadingHabits = (): UserReadingHabits => {
const readingHabits = get('readingHabits')
return readingHabits ? JSON.parse(readingHabits) : {
accessSpecificSections: [],
accessSpecificArticles: [],
articleReadingDuration: [],
readingDuration:0,
readAndParticipateInDiscussions: [],
useSearchTools: []
}
}
const setReadingHabits = (readingHabits: UserReadingHabits) => {
set('readingHabits', readingHabits)
}
const addReadingHabit = (readingHabit: ArticleReading) => {
const readingHabits = getReadingHabits()
const index = readingHabits.articleReadingDuration.findIndex((articleReading) => articleReading.articleId === readingHabit.articleId)
if (index !== -1) {
readingHabits.articleReadingDuration[index].readingDuration += readingHabit.readingDuration
setReadingHabits(readingHabits)
return
}
readingHabits.articleReadingDuration.push(readingHabit)
setReadingHabits(readingHabits)
}
const addAccessSpecificSection = (sectionId: number) => {
const readingHabits = getReadingHabits()
if (readingHabits.accessSpecificSections.includes(sectionId)) return
readingHabits.accessSpecificSections.push(sectionId)
setReadingHabits(readingHabits)
}
const addAccessSpecificArticle = (articleId: number) => {
const readingHabits = getReadingHabits()
if (readingHabits.accessSpecificArticles.includes(articleId)) return
readingHabits.accessSpecificArticles.push(articleId)
setReadingHabits(readingHabits)
}
const addReadAndParticipateInDiscussions = (discussionId: number) => {
const readingHabits = getReadingHabits()
if (readingHabits.readAndParticipateInDiscussions.includes(discussionId)) return
readingHabits.readAndParticipateInDiscussions.push(discussionId)
setReadingHabits(readingHabits)
}
const addUseSearchTools = (searchTool: string) => {
const readingHabits = getReadingHabits()
if (readingHabits.useSearchTools.includes(searchTool)) return
readingHabits.useSearchTools.push(searchTool)
setReadingHabits(readingHabits)
}
const addReadingDuration = (readingDuration: number) => {
const readingHabits = getReadingHabits()
readingHabits.readingDuration += readingDuration
setReadingHabits(readingHabits)
}
onBeforeUnmount(()=>{
addReadingDuration(Date.now() - startTime)
// check if entity is an article, if so add reading duration of article
if(entity){
addReadingHabit({
articleId: entity.id!,
readingDuration: Date.now() - startTime
})
}
})
return {
getReadingHabits,
setReadingHabits,
addReadingHabit,
addAccessSpecificSection,
addAccessSpecificArticle,
addReadAndParticipateInDiscussions,
addUseSearchTools,
addReadingDuration
}
}
+32
View File
@@ -0,0 +1,32 @@
const debounce = (fn: (...args: any[]) => void, delay = 0, immediate = false) => {
let timeout: string | number | NodeJS.Timeout
return (...args: any[]) => {
if (immediate && !timeout) fn(...args)
clearTimeout(timeout)
timeout = setTimeout(() => {
fn(...args)
}, delay)
}
}
const useDebouncedRef = (initialValue: any, delay?: number, immediate?: boolean) => {
const state = ref(initialValue)
const debouncedRef = customRef((track: () => void, trigger: () => void) => ({
get() {
track()
return state.value
},
set: debounce(
(value: any) => {
state.value = value
trigger()
},
delay,
immediate
),
}))
return debouncedRef
}
export default useDebouncedRef
+26
View File
@@ -0,0 +1,26 @@
import { type UseEventBusReturn } from '@vueuse/core'
type InputProps = {
group?: string;
}
export const useFormGroup = (inputProps?: InputProps) =>{
const profileFormEvent = inject<UseEventBusReturn<any, any>|undefined>('profile-form-event', undefined)
const profileFormStatus = inject('profile-form-status', {} as any)
const status = computed(()=>profileFormStatus?.value[inputProps?.group||''])
const emitFieldUpdate = (data:any)=>{
profileFormEvent?.emit({type:'update',field:inputProps?.group, data})
}
const changeStatus = (status:string)=>{
profileFormEvent?.emit({type:'status',field:inputProps?.group, data:status})
}
return {
status,
emitFieldUpdate,
changeStatus
}
}
+46
View File
@@ -0,0 +1,46 @@
export default () => {
/**
* Retrieves the value associated with the specified key from the local storage.
* @param key - The key of the value to retrieve.
* @returns The value associated with the specified key, or null if the key does not exist.
*/
function get(key: string): any {
return localStorage.getItem(key) ?? null;
}
/**
* Sets the value for a given key in the specified storage type.
* If the storage type is not provided, it defaults to "local" storage.
*
* @param key - The key to set the value for.
* @param payload - The value to be set.
* @param type - The type of storage to use ("local" or "session").
*/
function set(key: string, payload: any | any[], type: "local" | "session" = "local"): void {
// Use sessionStorage if type is "session"
const storage = type === "session" ? sessionStorage : localStorage;
// Convert payload to JSON string if it's an object
const data = typeof payload === "object" ? JSON.stringify(payload) : payload;
// Remove existing item before setting the new one
remove(key);
// Set item in storage
storage.setItem(key, data);
}
/**
* Removes the item with the specified key from the local storage.
* @param key - The key of the item to remove.
*/
function remove(key: string): void {
localStorage.removeItem(key);
}
return {
get,
set,
remove
}
}