Compare commits

..

3 Commits

Author SHA1 Message Date
Mehdi104797
4462c62e6c . 2025-03-16 13:55:53 +03:30
Mehdi104797
6299d5ec81 . 2025-03-16 12:45:50 +03:30
Mehdi104797
54fe65d31a . 2025-03-15 13:45:21 +03:30
12 changed files with 32 additions and 337 deletions

View File

@ -1,5 +1,5 @@
NUXT_PUBLIC_API_NAME=api/ VITE_API_NAME=api/
NUXT_PUBLIC_BASE_URL=http://192.168.23.60/ VITE_BASE_URL=http://192.168.23.60/
VITE_APP_NAME=Hadith VITE_APP_NAME=Hadith

View File

@ -1,289 +0,0 @@
1. Organize Your Code into Logical Sections
Structure your component script into clear sections to improve readability. A common approach is to group related logic together.
Example Structure:
<script setup>
// 1. Imports
import { ref, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
// 2. Reactive State
const count = ref(0)
const name = ref('')
// 3. Computed Properties
const doubledCount = computed(() => count.value * 2)
// 4. Functions / Methods
function increment() {
count.value++
}
// 5. Lifecycle Hooks
onMounted(() => {
console.log('Component mounted')
})
// 6. Watchers
watch(count, (newValue, oldValue) => {
console.log(`Count changed from ${oldValue} to ${newValue}`)
})
</script>
---
2. Use script setup Syntax
The <script setup> syntax is the recommended way to write Composition API components. It provides a more concise and intuitive syntax.
Example:
<script setup>
const message = ref('Hello, Vue 3!')
</script>
<template>
<p>{{ message }}</p>
</template>
---
3. Use Descriptive Variable and Function Names
Choose meaningful names for variables, functions, and computed properties to make your code self-documenting.
Example:
// Bad
const x = ref(0)
// Good
const userCount = ref(0)
---
4. Extract Reusable Logic into Composables
Move reusable logic into composables (custom hooks) to keep your components clean and promote code reuse.
Example Composable:
// composables/useCounter.js
import { ref } from 'vue'
export function useCounter(initialValue = 0) {
const count = ref(initialValue)
function increment() {
count.value++
}
function reset() {
count.value = initialValue
}
return {
count,
increment,
reset,
}
}
Usage in a Component:
<script setup>
import { useCounter } from '~/composables/useCounter'
const { count, increment } = useCounter()
</script>
<template>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
</template>
---
5. Use ref for Primitive Values and reactive for Objects
- Use ref for primitive values (e.g., numbers, strings, booleans).
- Use reactive for objects or arrays.
Example:
const count = ref(0) // Primitive value
const user = reactive({ name: 'John', age: 30 }) // Object
---
6. Use Computed Properties for Derived State
Use computed to create reactive properties that depend on other state. This ensures the derived state is always up-to-date.
Example:
const firstName = ref('John')
const lastName = ref('Doe')
const fullName = computed(() => `${firstName.value} ${lastName.value}`)
---
7. Use Watchers Sparingly
Watchers (watch and watchEffect) are powerful but can make your code harder to understand if overused. Prefer computed properties or event-driven updates where possible.
Example:
watch(count, (newValue, oldValue) => {
console.log(`Count changed from ${oldValue} to ${newValue}`)
})
---
8. Group Related Logic Together
Keep related reactive state, computed properties, and functions together to make your code easier to follow.
Example:
// User-related logic
const user = reactive({ name: 'John', age: 30 })
const isAdult = computed(() => user.age >= 18)
function updateUser(newName) {
user.name = newName
}
-----------
9. Use Lifecycle Hooks for Side Effects
Use lifecycle hooks (onMounted, onUnmounted, etc.) for side effects like fetching data or setting up event listeners.
Example:
onMounted(() => {
console.log('Component mounted')
fetchData()
})
onUnmounted(() => {
console.log('Component unmounted')
cleanup()
})
----------------
10. Use TypeScript for Better Type Safety
If your project uses TypeScript, leverage it to add type safety to your components.
Example:
<script setup lang="ts">
interface User {
name: string
age: number
}
const user = ref<User>({ name: 'John', age: 30 })
</script>
--------------
11. Keep Templates Clean
Avoid putting too much logic in your template. Instead, move complex logic into the script or composables.
Example:
<template>
<div>
<p>{{ fullName }}</p>
<button @click="increment">Increment</button>
</div>
</template>
<script setup>
const firstName = ref('John')
const lastName = ref('Doe')
const fullName = computed(() => `${firstName.value} ${lastName.value}`)
function increment() {
// Logic here
}
</script>
------------
12. Use provide and inject for Prop Drilling
Avoid prop drilling by using provide and inject to share state across deeply nested components.
Example:
// Parent component
import { provide, ref } from 'vue'
const theme = ref('dark')
provide('theme', theme)
// Child component
import { inject } from 'vue'
const theme = inject('theme')
-----------------
13. Use v-model for Two-Way Binding
Use v-model to simplify two-way binding between parent and child components.
Example:
<!-- Parent component -->
<template>
<ChildComponent v-model:name="userName" />
</template>
<script setup>
const userName = ref('John')
</script>
<!-- Child component -->
<template>
<input :value="name" @input="$emit('update:name', $event.target.value)" />
</template>
<script setup>
defineProps(['name'])
defineEmits(['update:name'])
</script>
----------
14. Use defineProps and defineEmits for TypeScript Support
When using TypeScript, use defineProps and defineEmits to define props and emits with type safety.
Example:
<script setup lang="ts">
const props = defineProps<{
title: string
count: number
}>()
const emit = defineEmits<{
(event: 'update:count', value: number): void
}>()
</script>
-------------
15. Use Scoped Styles
Use scoped styles (<style scoped>) to ensure styles are component-specific and dont leak into other components.
Example:
<style scoped>
.button {
background-color: blue;
}
</style>
------------------
16. Use Environment Variables
Use environment variables for configuration (e.g., API URLs) to keep your code flexible and secure.
Example:
const apiUrl = import.meta.env.VITE_API_URL
-------------
17. Write Unit Tests
Write unit tests for your components and composables to ensure they work as expected.
Example:
import { render } from '@testing-library/vue'
import MyComponent from '@/components/MyComponent.vue'
test('renders correctly', () => {
const { getByText } = render(MyComponent)
expect(getByText('Hello, Vue 3!')).toBeInTheDocument()
})

View File

@ -36,7 +36,7 @@ If it is, remove it from the index
git rm --cached systems/chat_ui git rm --cached systems/chat_ui
If system/chat_ui exits, remote it(chat_ui) If system/chat_ui exits, remote it(chat_ui)
rm -r systems/chat_ui rm -rf systems/chat_ui
Add the submodule Add the submodule
git submodule add https://github.com/example/repo.git systems/chat_ui git submodule add https://github.com/example/repo.git systems/chat_ui

18
app.vue
View File

@ -2,9 +2,27 @@
<UApp :locale="fa_ir"> <UApp :locale="fa_ir">
<NuxtLoadingIndicator /> <NuxtLoadingIndicator />
<NuxtRouteAnnouncer /> <NuxtRouteAnnouncer />
<!-- <DevOnly> -->
<!-- this component will only be rendered during development -->
<!-- <LazyDebugBar /> -->
<!-- if you ever require to have a replacement during production -->
<!-- be sure to test these using `nuxt preview` -->
<!-- <template #fallback> -->
<!-- <div>empty div for flex.justify-between</div> -->
<!-- </template> -->
<!-- </DevOnly> -->
<NuxtLayout> <NuxtLayout>
<!-- this component will be rendered on client-side -->
<!-- <NuxtClientFallback
fallback-tag="span"
fallback="NuxtClientFallback"
@ssr-error="logSomeError"
> -->
<NuxtPage /> <NuxtPage />
<!-- <BrokeInSsr /> -->
<!-- </NuxtClientFallback> -->
</NuxtLayout> </NuxtLayout>
</UApp> </UApp>
</template> </template>

View File

@ -1,26 +0,0 @@
// composables/useHadithaSearchComposable.js
import { useStorage } from "@vueuse/core";
export const useHadithaSearchComposable = <T>(url: string, options = {}) => {
// Get the authentication token (e.g., from a cookie or local storage)
// const token = useCookie('auth-token') // Assuming you store the token in a cookie
let token = useStorage("id_token", "GuestAccess");
const config = useRuntimeConfig();
console.info(config);
const baseURL =
config.public.NUXT_PUBLIC_BASE_URL + config.public.NUXT_PUBLIC_API_NAME;
// Add headers to the request
const headers = {
Authorization: token.value,
...options.headers, // Merge with any existing headers
};
// Use useFetch with the headers
return useFetch<T>(url, {
...options,
baseURL,
headers,
});
};

View File

@ -13,7 +13,7 @@ export default defineNuxtPlugin((nuxtApp) => {
onRequest({ request, options, error }) { onRequest({ request, options, error }) {
options.baseURL = options.baseURL =
import.meta.env.VITE_BASE_URL + import.meta.env.VITE_BASE_URL +
import.meta.env.NUXT_PUBLIC_API_NAME+ import.meta.env.VITE_API_NAME +
options.baseURL; options.baseURL;
if (token) { if (token) {

View File

@ -3,13 +3,12 @@ import { useStorage } from "@vueuse/core";
export default defineNuxtPlugin((nuxtApp) => { export default defineNuxtPlugin((nuxtApp) => {
let token = useStorage("id_token", "GuestAccess").value; let token = useStorage("id_token", "GuestAccess").value;
const config = useRuntimeConfig();
const api = $fetch.create({ const api = $fetch.create({
onRequest({ request, options, error }) { onRequest({ request, options, error }) {
options.baseURL = options.baseURL =
config.public.NUXT_PUBLIC_BASE_URL + import.meta.env.VITE_BASE_URL +
config.public.NUXT_PUBLIC_API_NAME + import.meta.env.VITE_API_NAME +
options.baseURL; options.baseURL;
if (token) { if (token) {
@ -41,14 +40,13 @@ export default defineNuxtPlugin((nuxtApp) => {
getRequest: (url, options = {}) => api(url, { method: "GET", ...options }), getRequest: (url, options = {}) => api(url, { method: "GET", ...options }),
postRequest: (url, body, options = {}) => postRequest: (url, body, options = {}) =>
api(url, { method: "POST", body, ...options }), api(url, { method: "POST", body, ...options }),
deleteRequest: (url, options = {}) => deleteRequest: (url, options = {}) => api(url, { method: "DELETE", ...options }),
api(url, { method: "DELETE", ...options }),
}; };
// Expose to useNuxtApp().$api and useNuxtApp().$http // Expose to useNuxtApp().$api and useNuxtApp().$http
return { return {
provide: { provide: {
http, http
}, },
}; };
}); });

View File

@ -9,12 +9,6 @@ export default [
path: "/haditha/search", path: "/haditha/search",
file: "~/systems/hadith_ui/pages/haditha/search/index.vue", file: "~/systems/hadith_ui/pages/haditha/search/index.vue",
}, },
{
name: "hadithaSearchShow",
path: "/haditha/search/:id/:slug?",
file: "~/systems/hadith_ui/pages/haditha/search/[id]/[slug]/index.vue",
},
{ {
name: "hadithaChatBot", name: "hadithaChatBot",
path: "/haditha/chat-bot", path: "/haditha/chat-bot",

@ -1 +1 @@
Subproject commit 2a5f878608e9cc9e508ab4de70337c2673344596 Subproject commit be90244a87e87eb66759bd10fabf5e881998b055

@ -1 +1 @@
Subproject commit 832f5dbf525ebddbcfa8873b5b3c88325f446a3c Subproject commit 953d98f3beb62044c320f5fcfb8a000f5e8264d0

View File

@ -275,7 +275,7 @@ export const userAvatar = (user = undefined) => {
if (user?.avatar && user?.avatar?.length) { if (user?.avatar && user?.avatar?.length) {
return ( return (
import.meta.env.VITE_BASE_URL + import.meta.env.VITE_BASE_URL +
import.meta.env.NUXT_PUBLIC_API_NAME+ import.meta.env.VITE_API_NAME +
fileUrl() + fileUrl() +
user.avatar user.avatar
); );
@ -362,9 +362,9 @@ export const getGroupAvatar = async (user = undefined) => {
const initials = nameArray[0].charAt(0); const initials = nameArray[0].charAt(0);
return generateAvatarFromChars(initials); return generateAvatarFromChars(initials);
} }
} } else return (await import("~/assets/common/img/default.svg")).default;
} }
} } else return (await import("~/assets/common/img/default.svg")).default;
} catch (err) { } catch (err) {
return (await import("~/assets/common/img/default.svg")).default; return (await import("~/assets/common/img/default.svg")).default;
} }

View File

@ -4,7 +4,7 @@ export async function useAPI<T>(
url: string | (() => string), url: string | (() => string),
options?: UseFetchOptions<T> options?: UseFetchOptions<T>
) { ) {
const prexFixUrlWithApiName = import.meta.env.NUXT_PUBLIC_API_NAME+ url; const prexFixUrlWithApiName = import.meta.env.VITE_API_NAME + url;
return await useFetch(prexFixUrlWithApiName, { return await useFetch(prexFixUrlWithApiName, {
...options, ...options,