diff --git a/.env b/.env index e7c2b7f..15a7229 100644 --- a/.env +++ b/.env @@ -1,3 +1,6 @@ +NUXT_PUBLIC_API_NAME=api/ +NUXT_PUBLIC_BASE_URL=/ + # For more information refere to documents: https://cli.vuejs.org/guide/mode-and-env.html#example-staging-mode VITE_GOOGLECLIENTID="1044522269248-903n0gpd6kv9slmmr7cp2o8u04ru78qv.apps.googleusercontent.com" diff --git a/.env.hadith b/.env.haditha similarity index 96% rename from .env.hadith rename to .env.haditha index d1eb86e..0cd8d87 100644 --- a/.env.hadith +++ b/.env.haditha @@ -1,4 +1,4 @@ -NUXT_PUBLIC_BASE_URL=http://192.168.23.60/ +NUXT_PUBLIC_BASE_URL=http://192.168.23.161/ VITE_APP_NAME=Hadith @@ -6,9 +6,9 @@ VITE_APP_NAME=Hadith ### Relative pathes for systems sass addressing ### # 0 : majles.tavasi.ir 1: qanon.parliran.ir VITE_BUILD_STATE=0 -VITE_BUILD_NAME=hadith +VITE_BUILD_NAME=haditha -VITE_IDB_NAME=hadith +VITE_IDB_NAME=haditha VITE_IDB_VERSION=1 VITE_ENABLE_IDB=1 diff --git a/.env.tavasi b/.env.tavasi index 011e3c9..4e31a43 100644 --- a/.env.tavasi +++ b/.env.tavasi @@ -1,5 +1,3 @@ - - NUXT_PUBLIC_BASE_URL=http://192.168.23.160/ VITE_APP_NAME=Majles diff --git a/.gitmodules b/.gitmodules index cbc0f45..990288b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "systems/hadith_ui"] path = systems/hadith_ui url = https://git2.tavasi.ir/front/hadith_ui.git +[submodule "systems/chat_ui"] + path = systems/chat_ui + url = https://git2.tavasi.ir/front/chat_ui.git diff --git a/COMPOSITION_API.md b/COMPOSITION_API.md new file mode 100644 index 0000000..a8a599e --- /dev/null +++ b/COMPOSITION_API.md @@ -0,0 +1,289 @@ +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: + + + +--- + +2. Use script setup Syntax + +The + + + +--- + +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: + + + + + +--- + +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: + + +-------------- + +11. Keep Templates Clean + +Avoid putting too much logic in your template. Instead, move complex logic into the script or composables. +Example: + + + + +------------ + +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: + + + + + + + + + + +---------- + +14. Use defineProps and defineEmits for TypeScript Support + +When using TypeScript, use defineProps and defineEmits to define props and emits with type safety. +Example: + + +------------- + +15. Use Scoped Styles + +Use scoped styles ( + +------------------ + +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() +}) \ No newline at end of file diff --git a/GIT_SUBMODULE.md b/GIT_SUBMODULE.md new file mode 100644 index 0000000..ce465df --- /dev/null +++ b/GIT_SUBMODULE.md @@ -0,0 +1,52 @@ +Add new repo: +git submodule add https://git2.tavasi.ir/front/chat_ui.git systems/chat_ui -f + +Cloning a Repository with Submodules +If you clone a repository that contains submodules, you'll need to initialize and update the submodules: +git clone +cd +git submodule init +git submodule update + +Or, you can do it in one step: +git clone --recurse-submodules + +Updating Submodules +To update a submodule to the latest commit on its branch: +git submodule update --remote + +## How to Remove an Existing Submodule + +If the path was previously added as a submodule, you need to remove it completely before re-adding it. Follow these steps: + +1. Remove the submodule entry from .gitmodules. +2. Remove the submodule from the working tree and index: git rm --cached . +3. Delete the submodule directory: rm -rf . +4. Stage the .gitmodules changes: git add .gitmodules. +5. Commit the changes: git commit -m "Removed submodule ". + +errors: + +# repo already exists and is not a valid git repo + +Check if the path is already tracked +git ls-files --stage systems/chat_ui (100644 0 ) + +If it is, remove it from the index +git rm --cached systems/chat_ui + +If system/chat_ui exits, remote it(chat_ui) +rm -r systems/chat_ui + +Add the submodule +git submodule add https://git2.tavasi.ir/front/chat_ui.git systems/chat_ui + +Commit the changes +git commit -m "Added submodule at systems/chat_ui" + +Verify the submodule +git submodule status + +(Optional) Initialize and Update the Submodule +If the submodule was added successfully but not initialized, run: +git submodule update --init --recursive diff --git a/app.vue b/app.vue index da2e0c1..c610603 100644 --- a/app.vue +++ b/app.vue @@ -2,58 +2,48 @@ - - - - - - - - - - - - - - diff --git a/components/global/TheSidebar.vue b/components/global/TheSidebar.vue index e651d4f..639034f 100644 --- a/components/global/TheSidebar.vue +++ b/components/global/TheSidebar.vue @@ -1,299 +1,309 @@ + + \ No newline at end of file diff --git a/components/other/PropertyBuilder.vue b/components/other/PropertyBuilder.vue index b0ad910..abd1627 100644 --- a/components/other/PropertyBuilder.vue +++ b/components/other/PropertyBuilder.vue @@ -86,13 +86,13 @@ import repoApi from "~/apis/repoApi"; import { mapState } from "pinia"; import { useCommonStore } from "~/stores/commonStore"; -import SelectComponentDefault from "~/components/SelectComponentDefault.vue"; -import SelectComponent from "~/components/SelectComponent.vue"; -import InputComponent from "~/components/InputComponent.vue"; -import LabelComponent from "~/components/LabelComponent.vue"; -import tagsComponent from "~/components/tagsComponent.vue"; -import DateComponent from "~/components/DateComponent.vue"; -import TextareaComponent from "~/components/TextareaComponent.vue"; +import SelectComponentDefault from "~/components/other/SelectComponentDefault.vue"; +import SelectComponent from "~/components/other/SelectComponent.vue"; +import InputComponent from "~/components/other/InputComponent.vue"; +import LabelComponent from "~/components/other/LabelComponent.vue"; +import tagsComponent from "~/components/other/tagsComponent.vue"; +import DateComponent from "~/components/other/DateComponent.vue"; +import TextareaComponent from "~/components/other/TextareaComponent.vue"; /** * @vue-data {Object} [listUpdatedText = {}] - متن‌های به‌روزشده در لیست. * @vue-data {undefined} [httpService = undefined] - سرویس HTTP برای درخواست‌ها. diff --git a/composables/useHadithaSearchComposable.ts b/composables/useHadithaSearchComposable.ts new file mode 100644 index 0000000..0eb2aaa --- /dev/null +++ b/composables/useHadithaSearchComposable.ts @@ -0,0 +1,26 @@ +// composables/useHadithaSearchComposable.js +import { useStorage } from "@vueuse/core"; + +export const useHadithaSearchComposable = (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(url, { + ...options, + baseURL, + headers, + }); +}; diff --git a/composables/useLocalStorage.ts b/composables/useLocalStorage.ts new file mode 100644 index 0000000..374a995 --- /dev/null +++ b/composables/useLocalStorage.ts @@ -0,0 +1,38 @@ +// composables/useLocalStorage.ts +import { ref, watchEffect } from "vue"; + +export const useLocalStorage = (key: string, defaultValue: T) => { + const state = ref(defaultValue); + + // Only run on client-side + if (process.client) { + const readValue = () => { + try { + const item = window.localStorage.getItem(key); + return item ? (JSON.parse(item) as T) : defaultValue; + } catch (error) { + console.warn(`Error reading localStorage key "${key}":`, error); + return defaultValue; + } + }; + + state.value = readValue(); + + watchEffect(() => { + try { + window.localStorage.setItem(key, JSON.stringify(state.value)); + } catch (error) { + console.warn(`Error setting localStorage key "${key}":`, error); + } + }); + + // Handle storage events from other tabs + window.addEventListener("storage", (event) => { + if (event.key === key) { + state.value = readValue(); + } + }); + } + + return state; +}; diff --git a/composables/useMyComposable.ts b/composables/useMyComposable.ts index 808ed6b..d50a48a 100644 --- a/composables/useMyComposable.ts +++ b/composables/useMyComposable.ts @@ -1,44 +1,44 @@ -import { useStorage } from "@vueuse/core"; +// import { useStorage } from "@vueuse/core"; -import { ref } from "vue"; -import { useCommonStore } from "~/stores/commonStore"; +// import { ref } from "vue"; +// import { useCommonStore } from "~/stores/commonStore"; -export function useMyComposable() { - const count = ref(0); +// export function useMyComposable() { +// const count = ref(0); - const increment = () => { - count.value++; - }; +// const increment = () => { +// count.value++; +// }; - const decrement = () => { - count.value--; - }; +// const decrement = () => { +// count.value--; +// }; - return { - count, - increment, - decrement, - }; -} +// return { +// count, +// increment, +// decrement, +// }; +// } -export function useGetSchema() { - const commonStore = useCommonStore(); +// export function useGetSchema() { +// const commonStore = useCommonStore(); - try { - return useAsyncData("shema", () => - $fetch("/api/ali", { - headers: { - headers: { Authorization: useStorage("id_token") }, - }, - method: "post", - body: { - organ: commonStore.organNameGetter, - system: "search", - build_state: buildState(), - }, - }) - ); - } catch (err) { - console.info(err); - } -} +// try { +// return useAsyncData("shema", () => +// $fetch("/api/ali", { +// headers: { +// headers: { Authorization: useStorage("id_token") }, +// }, +// method: "post", +// body: { +// organ: commonStore.organNameGetter, +// system: "search", +// build_state: buildState(), +// }, +// }) +// ); +// } catch (err) { +// console.info(err); +// } +// } diff --git a/dockerfile b/dockerfile new file mode 100644 index 0000000..3227324 --- /dev/null +++ b/dockerfile @@ -0,0 +1,14 @@ +FROM node:22 + +WORKDIR /app + + +COPY package*.json ./ +RUN npm install + +COPY . . +RUN npm run build-haditha + +EXPOSE 3000 + +CMD ["node", ".output/server/index.mjs"] \ No newline at end of file diff --git a/layouts/HadithLayoutdsdasdasd.vue b/layouts/HadithLayoutdsdasdasd.vue deleted file mode 100644 index 8f6b8b7..0000000 --- a/layouts/HadithLayoutdsdasdasd.vue +++ /dev/null @@ -1,17 +0,0 @@ - - - \ No newline at end of file diff --git a/layouts/default.vue b/layouts/default.vue index d1458dc..b54460f 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -1,167 +1,177 @@ @@ -169,7 +179,7 @@ import { mapState, mapActions } from "pinia"; import { useCommonStore } from "~/stores/commonStore"; -import {clearBodyClass} from "@manuals/utilities" +import { clearBodyClass } from "@manuals/utilities"; export default { mounted() { // this.setBodyClass("default-dashboard"); diff --git a/middleware/redirect.global.ts b/middleware/redirect.global.ts index 856bf34..590b9da 100644 --- a/middleware/redirect.global.ts +++ b/middleware/redirect.global.ts @@ -1,4 +1,7 @@ // middleware/redirect.js export default defineNuxtRouteMiddleware((to, from) => { - if (buildName() == "hadith" && to.path == '/') return navigateTo({ name: "hadith" }); + if (buildName() == "haditha" && to.path == "/") + return navigateTo({ name: "haditha" }); + else if (buildName() == "haditha" && to.path == "/login") + return navigateTo({ name: "hadithaLogin" }); }); diff --git a/mixins/authMixin.js b/mixins/authMixin.js index 4dbb056..da4ea5b 100644 --- a/mixins/authMixin.js +++ b/mixins/authMixin.js @@ -33,6 +33,8 @@ export default { ]), // callFrom : page | modal async authBase(methodName, callFrom = "page") { + const toast = useToast(); + // this.$v.$touch(); const route = useRoute(); const router = useRouter(); @@ -51,16 +53,19 @@ export default { this[methodName]() .then((res) => { - // mySwalToast({ - // title: res.message, - // icon: "success", - // timer: 2000, - // }); + toast.add({ + title: res.message, + icon: "success", + timer: 2000, + }); if (callFrom == "modal") { // fired event cached in the Group.vue and ChatList.vue const { $eventBus } = useNuxtApp(); - $eventBus.emit("authenticated-by-modal", route.query["invite-id"]); + $eventBus.emit( + "authenticated-by-modal", + route.query["invite-id"] + ); } // if redirected from chat system to relogin. else { @@ -81,10 +86,12 @@ export default { } }) .catch((err) => { - mySwalToast({ + toast.add({ title: err.message, icon: "error", + timer: 2000, }); + this.resetCaptcha(); }) .finally(() => { diff --git a/mixins/formBuilderMixin.js b/mixins/formBuilderMixin.js new file mode 100644 index 0000000..0967b80 --- /dev/null +++ b/mixins/formBuilderMixin.js @@ -0,0 +1,358 @@ +export default { + props: ["formElement", "keyValue"], + + data() { + return { + options: { + controls: [ + // "play-large", // The large play button in the center + //'restart', // Restart playback + // "rewind", // Rewind by the seek time (default 10 seconds) + "play", // Play/pause playback + // "fast-forward", // Fast forward by the seek time (default 10 seconds) + "progress", // The progress bar and scrubber for playback and buffering + "current-time", // The current time of playback + // "duration", // The full duration of the media + "mute", // Toggle mute + "volume", // Volume control + // "captions", // Toggle captions + "settings", // Settings menu + // "pip", // Picture-in-picture (currently Safari only) + // "airplay", // Airplay (currently Safari only) + "download", // Show a download button with a link to either the current source or a custom URL you specify in your options + // "fullscreen", // Toggle fullscreen + ], + speed: { selected: 1, options: [0.75, 1, 1.5, 2] }, + }, + hasError: false, + localFormElement: {}, + textValue: "", + emit_disable: false, + textValuePrev: "", + textDate: [], + objectValue: {}, // for select component {text, value} + isUpdateitem: false, + renderKey:1, + }; + }, + beforeMount() { + this.$root.$on("catch-form-builder-event", this.listenEventBus); + }, + beforeDestroy() { + this.$root.$off("catch-form-builder-event", this.listenEventBus); + }, + + mounted() { + // this.textValue = this.value; + // this.textItem = this.value + + this.disableEmitTemprory(2000); + + this.localFormElement = this.formElement; + this.textValuePrev = this.localFormElement.value; + this.initTextValue(); + this.textValuePrev = this.textValue; + // this.date = this.textValue; // for DateCompnent + }, + + watch: { + formElement: { + handler(newValue) { + this.localFormElement = newValue; + }, + deep: true, + nested: true, + }, + + textValue(newVal) { + // console.log(this.localFormElement.key, newVal) + if (this.textValuePrev == newVal) { + return; + } + let [emitValue, emitValueObject] = this.parseValueToEmit(newVal) + + // if (!this.emit_disable) + // console.log(this.localFormElement.key, newVal, emitValue, this.localFormElement.value) + if(this.localFormElement.value != emitValue) + this.$emit("take-value", emitValue); + + if (emitValueObject) this.parseAffectedToEventBus(emitValueObject); // for select only + else this.parseAffectedToEventBus(emitValue); + }, + }, + methods: { + incrementRenderKey(){ + this.renderKey = this.renderKey +1 + this.$forceUpdate(); + }, + + parseValueToEmit(newVal){ + let emitValue = newVal; + let emitValueObject = undefined; + + if (this.localFormElement?.type == "date") { + // console.info(newVal); + emitValue = newVal; + try { + if (this.localFormElement?.savetype == "timestamp") { + let dtStr = newVal; + // const dtStr = "2012/02/26"; + const [y, m, d] = dtStr.split(/-|\//); + const date = new Date(y, m - 1, d); + // emitValue = date.toISOString(); + emitValue = date.getTime()(); + } + // if( this.localFormElement?.subtype == 'time' ) + // return "HH:mm" + } catch { + emitValue = newVal; + } + // console.info(emitValue); + } + // input , textarea if multi items + else if (this.localFormElement?.isarray) { + let delim = this.localFormElement?.delimiter + ? this.localFormElement.delimiter + : "-"; + + emitValue = []; + newVal + .split(delim) + .filter((el) => el.trim()) + .forEach((el) => { + emitValue.push(el.trim()); + }); + // console.log(emitValue) + } else if (this.localFormElement.type == "select" && this.listOptions) { + // if(this.localFormElement.key == 'city'){ + // } + emitValue = newVal; + //برای ذدخیره در بک کدام مقدار را بفرستد + if (this.localFormElement.value_save) { + emitValueObject = this.listOptions.find( + (item) => item.value == newVal + ); + + if (emitValueObject && this.localFormElement.value_save == "title") { + emitValue = emitValueObject.title ?? emitValueObject.value; + } else if ( + emitValueObject && + this.localFormElement.value_save == "object" + ) { + emitValue = { + id: emitValueObject.value, + title: emitValueObject.title, + }; + } + } + } else if (this.localFormElement?.type == "number"){ + if(this.localFormElement?.step != 1){ + emitValue = parseFloat(newVal) + } + else + emitValue = parseInt(newVal) + } + else emitValue = newVal; + + return [emitValue, emitValueObject] + + }, + listenEventBus({ value, affectedTo }) { + // console.log(affectedTo.key, this.localFormElement.key); + if (affectedTo.key === this.localFormElement.key) { + try { + + // console.log(this.localFormElement.key, affectedTo, value); + // console.log(this[affectedTo.action]) + this[affectedTo.action](value); + + } catch (err) {} + } + }, + parseAffectedToEventBus(newValue) { + if (!this.localFormElement["affected-to"]) return; + + // console.log("parseAffectedToEvent", newValue); + // console.log(newValue); + + let affectedTo = this.localFormElement["affected-to"]; + // console.log(affectedTo); + + affectedTo.forEach((item_affectedTo) => { + let value = newValue; + if ( + typeof newValue == "object" && + item_affectedTo?.param && + newValue[item_affectedTo?.param] + ) + value = newValue[item_affectedTo?.param]; + + if (item_affectedTo?.emit) { + this.$emit( "action-affected-item", { action:item_affectedTo.emit, key: item_affectedTo.key, value}); + // console.log("action-affected-item", { action:item_affectedTo.emit, key: item_affectedTo.key, value}) + } else if (item_affectedTo?.action) { + this.$root.$emit("catch-form-builder-event", { + value: value, + affectedTo: item_affectedTo, + }); + } + }); + }, + disableEmitTemprory(timeout = 1000) { + this.emit_disable = true; + setTimeout(() => { + this.emit_disable = false; + }, timeout); + }, + + clearErrors() { + return true; + }, + getLabel() { + let label = this.localFormElement.label; + if (this.localFormElement?.required == "1") label = "*" + label; + return label; + }, + validate(ev) { + const value = ev.target.value; + if (this.localFormElement.validate) { + // چک کردن برای وجود الگو + if (value) { + let pattern = this.localFormElement.validate; + // اگر الگوی ورودی معتبر باشد، تنظیم می‌کنیم که مقدار مطابقت دارد یا خیر + this.hasError = new RegExp(pattern).test(value); + } else { + // اگر مقدار ورودی خالی باشد، خطا بر اساس الزامی بودن فیلد تعیین می‌شود + this.hasError = this.localFormElement?.required ? true : false; + } + } else { + // اگر الگوی validate وجود نداشته باشد، کاری انجام نمی‌دهیم + this.hasError = false; + } + // اعلان خطا به والد (component اصلی) + this.$emit("take-value-validate", this.hasError); + }, + + initTextValue(newValue=undefined) { + // console.log('initTextValue', this.localFormElement.key, newValue) + + let value = ""; + if(newValue) + value = newValue + else if(this.localFormElement.value) + value = this.localFormElement.value; + else if(this.localFormElement.value_defualt) + value = this.localFormElement.value_defualt + + + + // در همه حالت نباید این باشد اگر لازم شد باید پیش فرض تنظیم شود + // ذخیره هم نمیشود ...!!! + // if (!value && this.localFormElement.type == "select") { + // value = this.listOptions.length > 0 ? this.listOptions[0].value : ""; + // } + // console.log(this.localFormElement.key, value) + + var mValue = value ?? ""; + + if (this.localFormElement?.type == "date") { + // console.info("setTextValue", mValue); + try { + var date = ""; + if (mValue != "") { + if (this.localFormElement?.savetype == "timestamp") { + let timeWithMiliSeconds = mValue; + + if ( this.isUnixTimestamp(mValue) && mValue.toString().length <= 11) { + timeWithMiliSeconds = mValue * 1000; + } + date = this.$moment(new Date(timeWithMiliSeconds)).format( + "YYYY-MM-DD HH:mm" + ); + } else if ( + this.localFormElement?.savetype == "datetime" || + this.localFormElement?.savetype == "date" + ) { + date = this.$moment(new Date(mValue)).format("YYYY-MM-DD HH:mm"); + } else date = mValue; + } + this.textDate = date; + mValue = date + } catch { + this.textDate = mValue; + } + } else if (this.localFormElement?.isarray) { + if (value && Array.isArray(value)) { + let delim = this.localFormElement?.delimiter + ? this.localFormElement.delimiter + : "-"; + mValue = value.join(delim); + } else mValue = ""; + } else if (this.localFormElement.type == "select") { + if (this.localFormElement?.value_save == "title" && this.listOptions) { + // console.log('value_defualt', this.localFormElement.value_defualt) + let finded = this.listOptions.find((item) => { + if (item.title == value) { + return item; + } + }); + + if (finded) { + mValue = finded.value; + // console.log('finded', finded) + } else { + mValue = + this.listOptions.length > 0 ? this.listOptions[0].value : ""; + } + } else if (this.localFormElement?.value_save == "object") { + mValue = value.value; + } else mValue = value ?? ""; + } else { + mValue = value ?? ""; + } + + //نیازی به ارسال تغییر در واچ نیست + if(this.localFormElement.value == value ) + this.textValuePrev == value + + this.textValue = mValue + + // console.log(' this.textValue', this.localFormElement.key, this.textValue) + }, + isUnixTimestamp(value) { + // Check if the value is a number + if (typeof value !== "number" && !/^\d+$/.test(value)) { + return false; + } + // Convert to number if it's a string + value = parseInt(value); + // Unix timestamps are non-negative integers + return !isNaN(value) && value >= 0 && value % 1 === 0; + }, + + sendTextValue() { + this.$emit("keydown", { + text: this.textValue, + key: this.keyValue, + isUpdate: this.isUpdateitem, + }); + }, + + ////ااز هیچا فراخوانی نمیشه لذا کامنت کردم + //فقط برای select + // takeSelectValue($event, type) { + + // this.objectValue = { + // value: $event.target.value, + // text: $event.target.selectedOptions[0].text, + // }; + + // console.log('takeSelectValue',this.localFormElement.key , objectValue) + + // this.$emit("take-select-object", { + // type: type, + // objectValue: this.objectValue, + // }); + // }, + }, +}; diff --git a/mixins/settings/settingsMixin.js b/mixins/settings/settingsMixin.js index caf2db7..cb10acd 100644 --- a/mixins/settings/settingsMixin.js +++ b/mixins/settings/settingsMixin.js @@ -1,5 +1,5 @@ import { mapState, mapActions } from "pinia"; -import { useCommonStore } from "@stores/commonStore"; +import { useCommonStore } from "~/stores/commonStore"; export default { created() { diff --git a/nuxt.config.ts b/nuxt.config.ts index c57264a..b653a6c 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -2,6 +2,11 @@ import fs from "fs-extra"; import path from "path"; +import chat from "./routes/chat"; +import haditha from "./routes/haditha"; +import search from "./routes/search"; +import research from "./routes/research"; + const envs = import.meta.env; let sassEnvVariables = ""; @@ -13,20 +18,19 @@ for (let e in envs) { // dynamically importing styles. const buildName = import.meta.env.VITE_BUILD_NAME; -let mainStyle = `~/assets/common/scss/${buildName}-styles.scss`; - -if (buildName == "hadith") - mainStyle = `~/systems/${buildName}_ui/assets/${buildName}/scss/${buildName}.css`; export default defineNuxtConfig({ hooks: { "build:before": () => { - if (buildName == "hadith") { + if (buildName == "haditha") { const sourceDir = path.resolve( __dirname, - `systems/${buildName}_ui/assets/${buildName}/images` + `systems/${buildName.substring( + 0, + buildName.length - 1 + )}_ui/assets/${buildName}/images` ); // Source folder (e.g., assets/images) - const targetDir = path.resolve(__dirname, "public/img"); // Target folder (e.g., public/images) + const targetDir = path.resolve(__dirname, `public/img/${buildName}`); // Target folder (e.g., public/images) // Ensure the target directory exists fs.ensureDirSync(targetDir); @@ -40,96 +44,15 @@ export default defineNuxtConfig({ "pages:extend"(pages) { // Add custom routes - pages.push( - { - name: "search", - path: "/search", - file: "~/systems/search_ui/pages/search/index.vue", - }, - { - name: "searchNavigation", - path: "/search/lists", - file: "~/systems/search_ui/pages/search/lists.vue", - }, - { - name: "searchChart", - path: "/search/charts", - file: "~/systems/search_ui/pages/search/charts.vue", - }, - { - name: "showEntity", - path: "/search/:key/:id/show", - file: "~/systems/search_ui/pages/search/(show)/[key]/[id]/index.vue", - }, - { - name: "navigationView", - path: "/search/:key/:id/list", - file: "~/systems/search_ui/pages/search/(show)/[key]/[id]/index.vue", - }, - { - name: "entityResearch", - path: "/search/:key/:id/research", - file: "~/systems/search_ui/pages/search/(show)/[key]/[id]/index.vue", - }, - { - name: "entityResearch", - path: "/search/:key/:id/detail", - file: "~/systems/search_ui/pages/search/(show)/[key]/[id]/index.vue", - }, - // --------------------- start: hadith routes --------------------- - { - name: "hadith", - path: "/hadith", - file: "~/systems/hadith_ui/pages/hadith/index.vue", - }, - { - name: "hadithSearch", - path: "/hadith/search", - file: "~/systems/hadith_ui/pages/hadith/search/index.vue", - }, - { - name: "hadithChatBot", - path: "/hadith/chat-bot", - file: "~/systems/hadith_ui/pages/hadith/chat-bot.vue", - }, - { - name: "hadithFavorites", - path: "/hadith/favorites", - file: "~/systems/hadith_ui/pages/hadith/favorites/index.vue", - }, - { - name: "hadithLibrary", - path: "/hadith/library", - file: "~/systems/hadith_ui/pages/hadith/library/index.vue", - }, - { - name: "hadithLibraryShow", - path: "/hadith/library/:id/:slug?", - file: "~/systems/hadith_ui/pages/hadith/library/[id]/[slug]/index.vue", - }, - { - name: "hadithAbout", - path: "/hadith/about-us", - file: "~/systems/hadith_ui/pages/hadith/public-pages/about-us.vue", - }, - { - name: "hadithContact", - path: "/hadith/contact-us", - file: "~/systems/hadith_ui/pages/hadith/public-pages/ContactUs.vue", - }, - { - name: "hadithRules", - path: "/hadith/rules", - file: "~/systems/hadith_ui/pages/hadith/public-pages/rules.vue", - } - - // --------------------- end: hadith routes --------------------- - ); + pages.push(...search, ...research, ...haditha, ...chat); }, }, nitro: { compressPublicAssets: true, + prerender: { + routes: ["/haditha", "/haditha/about-us", "/haditha/contact-us"], // Pre-render these routes + }, }, colorMode: { @@ -172,6 +95,17 @@ export default defineNuxtConfig({ "@nuxt/image", // "@nuxtjs/supabase", ], + icon: { + customCollections: [ + { + prefix: "haditha", + dir: `./systems/${buildName.substring( + 0, + buildName.length - 1 + )}_ui/assets/${buildName}/font-icons/*.svg`, + }, + ], + }, // ui: { // prefix: 'Nuxt', //Use the prefix option to change the prefix of the components. Default: U // fonts: false, // Use the fonts option to enable or disable the @nuxt/fonts module. Default: true @@ -185,29 +119,10 @@ export default defineNuxtConfig({ // debug: process.env.NODE_ENV === 'development', // mode: 'init' // }, - image: { - inject: true, - quality: 80, - format: ["webp", "jpeg", "jpg", "png", "gif", "avif"], - screens: { - xs: 320, - sm: 576, - md: 768, - lg: 1199, - xl: 1400, - xxl: 1600, - "2xl": 1920, - }, - presets: { - avatar: { - modifiers: { - format: "jpg", - width: 25, - height: 24, - }, - }, - }, - }, + // image: { + // provider: "ipx", + // quality: 100, + // }, i18n: { vueI18n: "./i18n.config.ts", // if you are using custom path, default }, @@ -233,7 +148,7 @@ export default defineNuxtConfig({ }, }, css: [ - mainStyle, + customStyleLoader(), // "vue3-persian-datetime-picker/src/picker/assets/scss/style.scss", ], alias: { @@ -253,9 +168,11 @@ export default defineNuxtConfig({ "@pages": "~/pages", "@search": "~/systems/search_ui", "@research": "~/systems/research_ui", - "@hadith": "~/systems/hadith_ui", + "@haditha": "~/systems/hadith_ui", + "@chat": "~/systems/chat_ui", }, vite: { + assetsInclude: ['**/*.svg'], resolve: {}, // optimizeDeps: { // exclude: ["vue-demi"], @@ -275,6 +192,10 @@ export default defineNuxtConfig({ }, }, }, + build: { + analyze: true, + // transpile: ["echarts", "resize-detector", "echarts-wordcloud"], + }, // postcss: { // plugins: { // tailwindcss: {}, @@ -419,3 +340,13 @@ export default defineNuxtConfig({ // console.log(runtimeConfig.public.apiBase) // Resolve ~, ~~, @ and @@ aliases located within layers with respect to their layer source and root directories. +function customStyleLoader() { + let mainStyle = `~/assets/common/scss/${buildName}-styles.scss`; + if (buildName == "haditha") + mainStyle = `~/systems/${buildName.substring( + 0, + buildName.length - 1 + )}_ui/assets/${buildName}/scss/${buildName}.css`; + + return mainStyle; +} diff --git a/package-lock.json b/package-lock.json index 967f61b..d75fb73 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,8 @@ "@vueup/vue-quill": "^1.2.0", "axios": "^1.7.7", "bootstrap": "^5.3.3", + "codemirror": "^6.0.1", + "cropperjs": "^2.0.0", "docx": "^9.1.1", "echarts": "^5.5.1", "echarts-wordcloud": "^2.1.0", @@ -29,6 +31,8 @@ "i18next-vue": "^5.0.0", "jalali-moment": "^3.3.11", "jquery": "^3.7.1", + "lucide": "^0.477.0", + "lucide-vue-next": "^0.477.0", "mammoth": "^1.8.0", "mitt": "^3.0.1", "npm": "^11.1.0", @@ -42,6 +46,7 @@ "vue-draggable-next": "^2.2.1", "vue-echarts": "^7.0.3", "vue-i18n": "^10.0.1", + "vue-image-upload-resize": "^2.3.0", "vue-jalali-moment": "^1.0.0", "vue-jstree": "^2.1.6", "vue-multiselect": "^3.0.0", @@ -53,9 +58,12 @@ "vue3-persian-datetime-picker": "^1.2.2", "vue3-tree-vue": "^2.0.11", "vuejs-paginate": "^2.1.0", - "vuejs-paginate-next": "^1.0.2" + "vuejs-paginate-next": "^1.0.2", + "zod": "^3.24.2" }, "devDependencies": { + "@iconify-json/lucide": "^1.2.28", + "@iconify-json/vscode-icons": "^1.2.16", "@nuxt/test-utils": "^3.14.4", "@nuxtjs/i18n": "^9.0.0-rc.2", "@types/bootstrap": "^5.2.10", @@ -667,7 +675,6 @@ "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.3.tgz", "integrity": "sha512-1dNIOmiM0z4BIBwxmxEfA1yoxh1MF/6KPBbh20a5vphGV0ictKlgQsbJs6D6SkR6iJpGbpwRsa6PFMNlg9T9pQ==", "license": "MIT", - "peer": true, "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", @@ -712,7 +719,6 @@ "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.3.tgz", "integrity": "sha512-GSGfKxCo867P7EX1k2LoCrjuQFeqVgPGRRsSl4J4c0KMkD+k1y6WYvTQkzv0iZ8JhLJDujEvlnMchv4CZQLh3Q==", "license": "MIT", - "peer": true, "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.35.0", @@ -724,7 +730,6 @@ "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.8.tgz", "integrity": "sha512-PoWtZvo7c1XFeZWmmyaOp2G0XVbOnm+fJzvghqGAktBW3cufwJUWvSCcNG0ppXiBEM05mZu6RhMtXPv2hpllig==", "license": "MIT", - "peer": true, "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", @@ -748,6 +753,126 @@ "w3c-keyname": "^2.2.4" } }, + "node_modules/@cropper/element": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@cropper/element/-/element-2.0.0.tgz", + "integrity": "sha512-lsthn0nQq73GExUE7Mg/ss6Q3RXADGDv055hxoLFwvl/wGHgy6ZkYlfLZ/VmgBHC6jDK5IgPBFnqrPqlXWSGBA==", + "license": "MIT", + "dependencies": { + "@cropper/utils": "^2.0.0" + } + }, + "node_modules/@cropper/element-canvas": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@cropper/element-canvas/-/element-canvas-2.0.0.tgz", + "integrity": "sha512-GPtGJgSm92crJhhhwUsaMw3rz2KfJWWSz7kRAlufFEV/EHTP5+6r6/Z1BCGRna830i+Avqbm435XLOtA7PVJwA==", + "license": "MIT", + "dependencies": { + "@cropper/element": "^2.0.0", + "@cropper/utils": "^2.0.0" + } + }, + "node_modules/@cropper/element-crosshair": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@cropper/element-crosshair/-/element-crosshair-2.0.0.tgz", + "integrity": "sha512-KfPfyrdeFvUC31Ws7ATtcalWWSaMtrC6bMoCipZhqbUOE7wZoL4ecDSL6BUOZxPa74awZUqfzirCDjHvheBfyw==", + "license": "MIT", + "dependencies": { + "@cropper/element": "^2.0.0", + "@cropper/utils": "^2.0.0" + } + }, + "node_modules/@cropper/element-grid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@cropper/element-grid/-/element-grid-2.0.0.tgz", + "integrity": "sha512-i78SQ0IJTLFveKX6P7svkfMYVdgHrQ8ZmmEw8keFy9n1ZVbK+SK0UHK5FNMRNI/gtVhKJOGEnK/zeyjUdj4Iyw==", + "license": "MIT", + "dependencies": { + "@cropper/element": "^2.0.0", + "@cropper/utils": "^2.0.0" + } + }, + "node_modules/@cropper/element-handle": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@cropper/element-handle/-/element-handle-2.0.0.tgz", + "integrity": "sha512-ZJvW+0MkK9E8xYymGdoruaQn2kwjSHFpNSWinjyq6csuVQiCPxlX5ovAEDldmZ9MWePPtWEi3vLKQOo2Yb0T8g==", + "license": "MIT", + "dependencies": { + "@cropper/element": "^2.0.0", + "@cropper/utils": "^2.0.0" + } + }, + "node_modules/@cropper/element-image": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@cropper/element-image/-/element-image-2.0.0.tgz", + "integrity": "sha512-9BxiTS/aHRmrjopaFQb9mQQXmx4ruhYHGkDZMVz24AXpMFjUY6OpqrWse/WjzD9tfhMFvEdu17b3VAekcAgpeg==", + "license": "MIT", + "dependencies": { + "@cropper/element": "^2.0.0", + "@cropper/element-canvas": "^2.0.0", + "@cropper/utils": "^2.0.0" + } + }, + "node_modules/@cropper/element-selection": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@cropper/element-selection/-/element-selection-2.0.0.tgz", + "integrity": "sha512-ensNnbIfJsJ8bhbJTH/RXtk2URFvTOO4TvfRk461n2FPEC588D7rwBmUJxQg74IiTi4y1JbCI+6j+4LyzYBLCQ==", + "license": "MIT", + "dependencies": { + "@cropper/element": "^2.0.0", + "@cropper/element-canvas": "^2.0.0", + "@cropper/element-image": "^2.0.0", + "@cropper/utils": "^2.0.0" + } + }, + "node_modules/@cropper/element-shade": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@cropper/element-shade/-/element-shade-2.0.0.tgz", + "integrity": "sha512-jv/2bbNZnhU4W+T4G0c8ADocLIZvQFTXgCf2RFDNhI5UVxurzWBnDdb8Mx8LnVplnkTqO+xUmHZYve0CwgWo+Q==", + "license": "MIT", + "dependencies": { + "@cropper/element": "^2.0.0", + "@cropper/element-canvas": "^2.0.0", + "@cropper/element-selection": "^2.0.0", + "@cropper/utils": "^2.0.0" + } + }, + "node_modules/@cropper/element-viewer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@cropper/element-viewer/-/element-viewer-2.0.0.tgz", + "integrity": "sha512-zY+3VRN5TvpM8twlphYtXw0tzJL2VgzeK7ufhL1BixVqOdRxwP13TprYIhqwGt9EW/SyJZUiaIu396T89kRX8A==", + "license": "MIT", + "dependencies": { + "@cropper/element": "^2.0.0", + "@cropper/element-canvas": "^2.0.0", + "@cropper/element-image": "^2.0.0", + "@cropper/element-selection": "^2.0.0", + "@cropper/utils": "^2.0.0" + } + }, + "node_modules/@cropper/elements": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@cropper/elements/-/elements-2.0.0.tgz", + "integrity": "sha512-PQkPo1nUjxLFUQuHYu+6atfHxpX9B41Xribao6wpvmvmNIFML6LQdNqqWYb6LyM7ujsu71CZdBiMT5oetjJVoQ==", + "license": "MIT", + "dependencies": { + "@cropper/element": "^2.0.0", + "@cropper/element-canvas": "^2.0.0", + "@cropper/element-crosshair": "^2.0.0", + "@cropper/element-grid": "^2.0.0", + "@cropper/element-handle": "^2.0.0", + "@cropper/element-image": "^2.0.0", + "@cropper/element-selection": "^2.0.0", + "@cropper/element-shade": "^2.0.0", + "@cropper/element-viewer": "^2.0.0" + } + }, + "node_modules/@cropper/utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@cropper/utils/-/utils-2.0.0.tgz", + "integrity": "sha512-cprLYr+7kK3faGgoOsTW9gIn5sefDr2KwOmgyjzIXk+8PLpW8FgFKEg5FoWfRD5zMAmkCBuX6rGKDK3VdUEGrg==", + "license": "MIT" + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.24.2", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", @@ -1463,6 +1588,26 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@iconify-json/lucide": { + "version": "1.2.28", + "resolved": "https://registry.npmjs.org/@iconify-json/lucide/-/lucide-1.2.28.tgz", + "integrity": "sha512-SPeAoh1YKhALpNSto/FBspf3GZ0eAr3ka/OI7cJJ5HljLzycIITv0s4Rd2+sRVzFtD1I991mJJmYohQeOSZ+Og==", + "dev": true, + "license": "ISC", + "dependencies": { + "@iconify/types": "*" + } + }, + "node_modules/@iconify-json/vscode-icons": { + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@iconify-json/vscode-icons/-/vscode-icons-1.2.16.tgz", + "integrity": "sha512-hstc2yVq2UJ6v6FrgjftzXRvphGZBsKxvSeXoFLP1Hgx89TPZKrGE5SV6vqsoeIlLYaQ7OZbXmAoVGroTfGmVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@iconify/types": "*" + } + }, "node_modules/@iconify/collections": { "version": "1.0.516", "resolved": "https://registry.npmjs.org/@iconify/collections/-/collections-1.0.516.tgz", @@ -6302,6 +6447,12 @@ "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", "license": "MIT" }, + "node_modules/blueimp-canvas-to-blob": { + "version": "3.29.0", + "resolved": "https://registry.npmjs.org/blueimp-canvas-to-blob/-/blueimp-canvas-to-blob-3.29.0.tgz", + "integrity": "sha512-0pcSSGxC0QxT+yVkivxIqW0Y4VlO2XSDPofBAqoJ1qJxgH9eiUDLv50Rixij2cDuEfx4M6DpD9UGZpRhT5Q8qg==", + "license": "MIT" + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -6845,7 +6996,6 @@ "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz", "integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==", "license": "MIT", - "peer": true, "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/commands": "^6.0.0", @@ -7112,8 +7262,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/croner": { "version": "9.0.0", @@ -7133,6 +7282,16 @@ "cronstrue": "bin/cli.js" } }, + "node_modules/cropperjs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-2.0.0.tgz", + "integrity": "sha512-TO2j0Qre01kPHbow4FuTrbdEB4jTmGRySxW49jyEIqlJZuEBfrvCTT0vC3eRB2WBXudDfKi1Onako6DKWKxeAQ==", + "license": "MIT", + "dependencies": { + "@cropper/elements": "^2.0.0", + "@cropper/utils": "^2.0.0" + } + }, "node_modules/cross-fetch": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", @@ -10934,6 +11093,21 @@ "dev": true, "license": "MIT" }, + "node_modules/lucide": { + "version": "0.477.0", + "resolved": "https://registry.npmjs.org/lucide/-/lucide-0.477.0.tgz", + "integrity": "sha512-lEgt1ni9sKohbLsYWSnM3mKVRkvUrJ3Ijj01RAdM5F0iyvxkCcy3gPrb1G2ux6zE4y20ptcitfMa0OOFXI57gw==", + "license": "ISC" + }, + "node_modules/lucide-vue-next": { + "version": "0.477.0", + "resolved": "https://registry.npmjs.org/lucide-vue-next/-/lucide-vue-next-0.477.0.tgz", + "integrity": "sha512-C7azIKO7aJKf5MD7OIzV7NRDtnjXH3KSXfyJgGqRIMemuMzW/9esuMxDXIXDhBZcJgRtXMUN0FcJwOJZQ8SywA==", + "license": "ISC", + "peerDependencies": { + "vue": ">=3.0.1" + } + }, "node_modules/magic-regexp": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/magic-regexp/-/magic-regexp-0.8.0.tgz", @@ -20434,6 +20608,16 @@ "vue": "^3.0.0" } }, + "node_modules/vue-image-upload-resize": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vue-image-upload-resize/-/vue-image-upload-resize-2.3.0.tgz", + "integrity": "sha512-ElzyAVCluiDt8xSZkSK9FbuLY5mr23JlO4cHyyRo86RfEGLWtvXrTq7vYOgDstT8rNBmnTgNCkPKc0rpmyl1yA==", + "license": "MIT", + "dependencies": { + "blueimp-canvas-to-blob": "^3.14.0", + "vue": "^2.5.17" + } + }, "node_modules/vue-jalali-moment": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/vue-jalali-moment/-/vue-jalali-moment-1.0.0.tgz", @@ -21037,6 +21221,15 @@ "node": ">= 14" } }, + "node_modules/zod": { + "version": "3.24.2", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", + "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "node_modules/zrender": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/zrender/-/zrender-5.6.0.tgz", diff --git a/package.json b/package.json index cd2da1c..8728875 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,8 @@ "postinstall": "nuxt prepare", "dev-tavasi": "env-cmd -f .env.tavasi nuxt dev --host --inspect", "dev-monir": "env-cmd -f .env.monir nuxt dev --host --inspect", - "dev-hadith": "env-cmd -f .env.hadith nuxt dev --host --inspect", - "build-hadith": "env-cmd -f .env.hadith nuxt build" + "dev-haditha": "env-cmd -f .env.haditha nuxt dev --host --inspect", + "build-haditha": "env-cmd -f .env.haditha nuxt build" }, "dependencies": { "@nuxt/image": "^1.8.1", @@ -25,6 +25,8 @@ "@vueup/vue-quill": "^1.2.0", "axios": "^1.7.7", "bootstrap": "^5.3.3", + "codemirror": "^6.0.1", + "cropperjs": "^2.0.0", "docx": "^9.1.1", "echarts": "^5.5.1", "echarts-wordcloud": "^2.1.0", @@ -37,6 +39,8 @@ "i18next-vue": "^5.0.0", "jalali-moment": "^3.3.11", "jquery": "^3.7.1", + "lucide": "^0.477.0", + "lucide-vue-next": "^0.477.0", "mammoth": "^1.8.0", "mitt": "^3.0.1", "npm": "^11.1.0", @@ -50,6 +54,7 @@ "vue-draggable-next": "^2.2.1", "vue-echarts": "^7.0.3", "vue-i18n": "^10.0.1", + "vue-image-upload-resize": "^2.3.0", "vue-jalali-moment": "^1.0.0", "vue-jstree": "^2.1.6", "vue-multiselect": "^3.0.0", @@ -61,9 +66,12 @@ "vue3-persian-datetime-picker": "^1.2.2", "vue3-tree-vue": "^2.0.11", "vuejs-paginate": "^2.1.0", - "vuejs-paginate-next": "^1.0.2" + "vuejs-paginate-next": "^1.0.2", + "zod": "^3.24.2" }, "devDependencies": { + "@iconify-json/lucide": "^1.2.28", + "@iconify-json/vscode-icons": "^1.2.16", "@nuxt/test-utils": "^3.14.4", "@nuxtjs/i18n": "^9.0.0-rc.2", "@types/bootstrap": "^5.2.10", diff --git a/pages/index.vue b/pages/index.vue index 4f56816..888efa5 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -5,7 +5,7 @@ - + diff --git a/plugins/api.ts b/plugins/api.ts index c9895c0..fe822a1 100644 --- a/plugins/api.ts +++ b/plugins/api.ts @@ -6,14 +6,16 @@ import { useStorage } from "@vueuse/core"; // lsToken = "GuestAccess"; export default defineNuxtPlugin((nuxtApp) => { + const config = useRuntimeConfig(); + // const { session } = useUserSession(); // const authStore = useAuthStore(); let token = useStorage("id_token", "GuestAccess").value; const api = $fetch.create({ onRequest({ request, options, error }) { options.baseURL = - import.meta.env.VITE_BASE_URL + - import.meta.env.VITE_API_NAME + + config.public.NUXT_PUBLIC_BASE_URL + + config.public.NUXT_PUBLIC_API_NAME + options.baseURL; if (token) { diff --git a/plugins/httpService.ts b/plugins/httpService.ts index 704f4f0..880a3b7 100644 --- a/plugins/httpService.ts +++ b/plugins/httpService.ts @@ -3,12 +3,13 @@ import { useStorage } from "@vueuse/core"; export default defineNuxtPlugin((nuxtApp) => { let token = useStorage("id_token", "GuestAccess").value; + const config = useRuntimeConfig(); const api = $fetch.create({ onRequest({ request, options, error }) { options.baseURL = - import.meta.env.VITE_BASE_URL + - import.meta.env.VITE_API_NAME + + config.public.NUXT_PUBLIC_BASE_URL + + config.public.NUXT_PUBLIC_API_NAME + options.baseURL; if (token) { @@ -37,16 +38,17 @@ export default defineNuxtPlugin((nuxtApp) => { // Add custom methods for GET, POST, and DELETE const http = { - getRequest: (url, options = {}) => api(url, { method: "GET", ...options }), - postRequest: (url, body, options = {}) => + getRequest: (url: string, options = {}) => api(url, { method: "GET", ...options }), + postRequest: (url: string, body: any, options = {}) => api(url, { method: "POST", body, ...options }), - deleteRequest: (url, options = {}) => api(url, { method: "DELETE", ...options }), + deleteRequest: (url: string, options = {}) => + api(url, { method: "DELETE", ...options }), }; // Expose to useNuxtApp().$api and useNuxtApp().$http return { provide: { - http + http, }, }; }); diff --git a/plugins/vuelidate.ts b/plugins/vuelidate.ts index 15ad641..7ab28b0 100644 --- a/plugins/vuelidate.ts +++ b/plugins/vuelidate.ts @@ -4,23 +4,28 @@ // createApp.use(Vuelidate); import { useVuelidate } from '@vuelidate/core' -import { required, minLength } from '@vuelidate/validators' +// import { required, minLength } from '@vuelidate/validators' -export default defineNuxtPlugin((nuxtApp) => { - nuxtApp.vueApp.use(() => { -// // Example of global setup, but typically you'd handle this in the component -// const state = reactive({ -// firstName: '' -// }) -// const rules = { -// firstName: { -// required, -// minLength: minLength(2) -// } -// } -// const v$ = useVuelidate(rules, state) -// return v$; -// // Return the v$ instance or any other necessary setup - }) -}) +// export default defineNuxtPlugin((nuxtApp) => { +// nuxtApp.vueApp.use((useVuelidate) => { +// // // Example of global setup, but typically you'd handle this in the component +// // const state = reactive({ +// // firstName: '' +// // }) +// // const rules = { +// // firstName: { +// // required, +// // minLength: minLength(2) +// // } +// // } +// // const v$ = useVuelidate(rules, state) +// // return v$; +// // // Return the v$ instance or any other necessary setup +// }) +// }) + + +export default defineNuxtPlugin(nuxtApp => { + nuxtApp.provide('vuelidate', useVuelidate) +}) \ No newline at end of file diff --git a/public/img/haditha/background-1.webp b/public/img/haditha/background-1.webp new file mode 100644 index 0000000..9cd5100 Binary files /dev/null and b/public/img/haditha/background-1.webp differ diff --git a/public/img/background.png b/public/img/haditha/background.png similarity index 100% rename from public/img/background.png rename to public/img/haditha/background.png diff --git a/public/img/background.svg b/public/img/haditha/background.svg similarity index 100% rename from public/img/background.svg rename to public/img/haditha/background.svg diff --git a/public/img/haditha/background.webp b/public/img/haditha/background.webp new file mode 100644 index 0000000..f08545d Binary files /dev/null and b/public/img/haditha/background.webp differ diff --git a/public/img/box-1-bgi.svg b/public/img/haditha/box-1-bgi.svg similarity index 100% rename from public/img/box-1-bgi.svg rename to public/img/haditha/box-1-bgi.svg diff --git a/public/img/card-one-bgi.png b/public/img/haditha/card-one-bgi.png similarity index 100% rename from public/img/card-one-bgi.png rename to public/img/haditha/card-one-bgi.png diff --git a/public/img/haditha/card-one-bgi.webp b/public/img/haditha/card-one-bgi.webp new file mode 100644 index 0000000..bb918b3 Binary files /dev/null and b/public/img/haditha/card-one-bgi.webp differ diff --git a/public/img/card-one.png b/public/img/haditha/card-one.png similarity index 100% rename from public/img/card-one.png rename to public/img/haditha/card-one.png diff --git a/public/img/haditha/card-one.webp b/public/img/haditha/card-one.webp new file mode 100644 index 0000000..6706581 Binary files /dev/null and b/public/img/haditha/card-one.webp differ diff --git a/public/img/card-three-bgi.png b/public/img/haditha/card-three-bgi.png similarity index 100% rename from public/img/card-three-bgi.png rename to public/img/haditha/card-three-bgi.png diff --git a/public/img/haditha/card-three-bgi.webp b/public/img/haditha/card-three-bgi.webp new file mode 100644 index 0000000..aba5d6b Binary files /dev/null and b/public/img/haditha/card-three-bgi.webp differ diff --git a/public/img/card-three.png b/public/img/haditha/card-three.png similarity index 100% rename from public/img/card-three.png rename to public/img/haditha/card-three.png diff --git a/public/img/haditha/card-three.webp b/public/img/haditha/card-three.webp new file mode 100644 index 0000000..7d5e991 Binary files /dev/null and b/public/img/haditha/card-three.webp differ diff --git a/public/img/card-two-bgi.png b/public/img/haditha/card-two-bgi.png similarity index 100% rename from public/img/card-two-bgi.png rename to public/img/haditha/card-two-bgi.png diff --git a/public/img/haditha/card-two-bgi.webp b/public/img/haditha/card-two-bgi.webp new file mode 100644 index 0000000..4b64a18 Binary files /dev/null and b/public/img/haditha/card-two-bgi.webp differ diff --git a/public/img/card-two.png b/public/img/haditha/card-two.png similarity index 100% rename from public/img/card-two.png rename to public/img/haditha/card-two.png diff --git a/public/img/haditha/card-two.webp b/public/img/haditha/card-two.webp new file mode 100644 index 0000000..523072d Binary files /dev/null and b/public/img/haditha/card-two.webp differ diff --git a/public/img/chevron-down.svg b/public/img/haditha/chevron-down.svg similarity index 100% rename from public/img/chevron-down.svg rename to public/img/haditha/chevron-down.svg diff --git a/public/img/haditha/fav-icons/android-icon-144x144.png b/public/img/haditha/fav-icons/android-icon-144x144.png new file mode 100644 index 0000000..4fcc24c Binary files /dev/null and b/public/img/haditha/fav-icons/android-icon-144x144.png differ diff --git a/public/img/haditha/fav-icons/android-icon-192x192.png b/public/img/haditha/fav-icons/android-icon-192x192.png new file mode 100644 index 0000000..c8683e2 Binary files /dev/null and b/public/img/haditha/fav-icons/android-icon-192x192.png differ diff --git a/public/img/haditha/fav-icons/android-icon-36x36.png b/public/img/haditha/fav-icons/android-icon-36x36.png new file mode 100644 index 0000000..d56a1e5 Binary files /dev/null and b/public/img/haditha/fav-icons/android-icon-36x36.png differ diff --git a/public/img/haditha/fav-icons/android-icon-48x48.png b/public/img/haditha/fav-icons/android-icon-48x48.png new file mode 100644 index 0000000..5e46d15 Binary files /dev/null and b/public/img/haditha/fav-icons/android-icon-48x48.png differ diff --git a/public/img/haditha/fav-icons/android-icon-72x72.png b/public/img/haditha/fav-icons/android-icon-72x72.png new file mode 100644 index 0000000..fd6dd34 Binary files /dev/null and b/public/img/haditha/fav-icons/android-icon-72x72.png differ diff --git a/public/img/haditha/fav-icons/android-icon-96x96.png b/public/img/haditha/fav-icons/android-icon-96x96.png new file mode 100644 index 0000000..7020428 Binary files /dev/null and b/public/img/haditha/fav-icons/android-icon-96x96.png differ diff --git a/public/img/haditha/fav-icons/apple-icon-114x114.png b/public/img/haditha/fav-icons/apple-icon-114x114.png new file mode 100644 index 0000000..7dd32f8 Binary files /dev/null and b/public/img/haditha/fav-icons/apple-icon-114x114.png differ diff --git a/public/img/haditha/fav-icons/apple-icon-120x120.png b/public/img/haditha/fav-icons/apple-icon-120x120.png new file mode 100644 index 0000000..d9bc867 Binary files /dev/null and b/public/img/haditha/fav-icons/apple-icon-120x120.png differ diff --git a/public/img/haditha/fav-icons/apple-icon-144x144.png b/public/img/haditha/fav-icons/apple-icon-144x144.png new file mode 100644 index 0000000..4fcc24c Binary files /dev/null and b/public/img/haditha/fav-icons/apple-icon-144x144.png differ diff --git a/public/img/haditha/fav-icons/apple-icon-152x152.png b/public/img/haditha/fav-icons/apple-icon-152x152.png new file mode 100644 index 0000000..0879fba Binary files /dev/null and b/public/img/haditha/fav-icons/apple-icon-152x152.png differ diff --git a/public/img/haditha/fav-icons/apple-icon-180x180.png b/public/img/haditha/fav-icons/apple-icon-180x180.png new file mode 100644 index 0000000..4d7527b Binary files /dev/null and b/public/img/haditha/fav-icons/apple-icon-180x180.png differ diff --git a/public/img/haditha/fav-icons/apple-icon-57x57.png b/public/img/haditha/fav-icons/apple-icon-57x57.png new file mode 100644 index 0000000..e498f7b Binary files /dev/null and b/public/img/haditha/fav-icons/apple-icon-57x57.png differ diff --git a/public/img/haditha/fav-icons/apple-icon-60x60.png b/public/img/haditha/fav-icons/apple-icon-60x60.png new file mode 100644 index 0000000..8270b64 Binary files /dev/null and b/public/img/haditha/fav-icons/apple-icon-60x60.png differ diff --git a/public/img/haditha/fav-icons/apple-icon-72x72.png b/public/img/haditha/fav-icons/apple-icon-72x72.png new file mode 100644 index 0000000..fd6dd34 Binary files /dev/null and b/public/img/haditha/fav-icons/apple-icon-72x72.png differ diff --git a/public/img/haditha/fav-icons/apple-icon-76x76.png b/public/img/haditha/fav-icons/apple-icon-76x76.png new file mode 100644 index 0000000..e52a334 Binary files /dev/null and b/public/img/haditha/fav-icons/apple-icon-76x76.png differ diff --git a/public/img/haditha/fav-icons/apple-icon-precomposed.png b/public/img/haditha/fav-icons/apple-icon-precomposed.png new file mode 100644 index 0000000..2b455ee Binary files /dev/null and b/public/img/haditha/fav-icons/apple-icon-precomposed.png differ diff --git a/public/img/haditha/fav-icons/apple-icon.png b/public/img/haditha/fav-icons/apple-icon.png new file mode 100644 index 0000000..2b455ee Binary files /dev/null and b/public/img/haditha/fav-icons/apple-icon.png differ diff --git a/public/img/haditha/fav-icons/browserconfig.xml b/public/img/haditha/fav-icons/browserconfig.xml new file mode 100644 index 0000000..c554148 --- /dev/null +++ b/public/img/haditha/fav-icons/browserconfig.xml @@ -0,0 +1,2 @@ + +#ffffff \ No newline at end of file diff --git a/public/img/haditha/fav-icons/favicon-16x16.png b/public/img/haditha/fav-icons/favicon-16x16.png new file mode 100644 index 0000000..ecd0126 Binary files /dev/null and b/public/img/haditha/fav-icons/favicon-16x16.png differ diff --git a/public/img/haditha/fav-icons/favicon-32x32.png b/public/img/haditha/fav-icons/favicon-32x32.png new file mode 100644 index 0000000..9f8ea97 Binary files /dev/null and b/public/img/haditha/fav-icons/favicon-32x32.png differ diff --git a/public/img/haditha/fav-icons/favicon-96x96.png b/public/img/haditha/fav-icons/favicon-96x96.png new file mode 100644 index 0000000..7020428 Binary files /dev/null and b/public/img/haditha/fav-icons/favicon-96x96.png differ diff --git a/public/img/haditha/fav-icons/favicon.ico b/public/img/haditha/fav-icons/favicon.ico new file mode 100644 index 0000000..b85be8f Binary files /dev/null and b/public/img/haditha/fav-icons/favicon.ico differ diff --git a/public/img/haditha/fav-icons/manifest.json b/public/img/haditha/fav-icons/manifest.json new file mode 100644 index 0000000..013d4a6 --- /dev/null +++ b/public/img/haditha/fav-icons/manifest.json @@ -0,0 +1,41 @@ +{ + "name": "App", + "icons": [ + { + "src": "\/android-icon-36x36.png", + "sizes": "36x36", + "type": "image\/png", + "density": "0.75" + }, + { + "src": "\/android-icon-48x48.png", + "sizes": "48x48", + "type": "image\/png", + "density": "1.0" + }, + { + "src": "\/android-icon-72x72.png", + "sizes": "72x72", + "type": "image\/png", + "density": "1.5" + }, + { + "src": "\/android-icon-96x96.png", + "sizes": "96x96", + "type": "image\/png", + "density": "2.0" + }, + { + "src": "\/android-icon-144x144.png", + "sizes": "144x144", + "type": "image\/png", + "density": "3.0" + }, + { + "src": "\/android-icon-192x192.png", + "sizes": "192x192", + "type": "image\/png", + "density": "4.0" + } + ] +} \ No newline at end of file diff --git a/public/img/haditha/fav-icons/ms-icon-144x144.png b/public/img/haditha/fav-icons/ms-icon-144x144.png new file mode 100644 index 0000000..4fcc24c Binary files /dev/null and b/public/img/haditha/fav-icons/ms-icon-144x144.png differ diff --git a/public/img/haditha/fav-icons/ms-icon-150x150.png b/public/img/haditha/fav-icons/ms-icon-150x150.png new file mode 100644 index 0000000..a014050 Binary files /dev/null and b/public/img/haditha/fav-icons/ms-icon-150x150.png differ diff --git a/public/img/haditha/fav-icons/ms-icon-310x310.png b/public/img/haditha/fav-icons/ms-icon-310x310.png new file mode 100644 index 0000000..b86fa21 Binary files /dev/null and b/public/img/haditha/fav-icons/ms-icon-310x310.png differ diff --git a/public/img/haditha/fav-icons/ms-icon-70x70.png b/public/img/haditha/fav-icons/ms-icon-70x70.png new file mode 100644 index 0000000..da737c9 Binary files /dev/null and b/public/img/haditha/fav-icons/ms-icon-70x70.png differ diff --git a/public/img/haditha-title.png b/public/img/haditha/haditha-title.png similarity index 100% rename from public/img/haditha-title.png rename to public/img/haditha/haditha-title.png diff --git a/public/img/haditha-title.svg b/public/img/haditha/haditha-title.svg similarity index 100% rename from public/img/haditha-title.svg rename to public/img/haditha/haditha-title.svg diff --git a/public/img/location.png b/public/img/haditha/location.png similarity index 100% rename from public/img/location.png rename to public/img/haditha/location.png diff --git a/public/img/haditha/location.webp b/public/img/haditha/location.webp new file mode 100644 index 0000000..3fa6374 Binary files /dev/null and b/public/img/haditha/location.webp differ diff --git a/public/img/logo.png b/public/img/haditha/logo.png similarity index 100% rename from public/img/logo.png rename to public/img/haditha/logo.png diff --git a/public/img/logo.svg b/public/img/haditha/logo.svg similarity index 100% rename from public/img/logo.svg rename to public/img/haditha/logo.svg diff --git a/public/img/haditha/logo.webp b/public/img/haditha/logo.webp new file mode 100644 index 0000000..62c2a06 Binary files /dev/null and b/public/img/haditha/logo.webp differ diff --git a/public/img/haditha/mobile/backgorund.png b/public/img/haditha/mobile/backgorund.png new file mode 100644 index 0000000..75d33d7 Binary files /dev/null and b/public/img/haditha/mobile/backgorund.png differ diff --git a/public/img/haditha/mobile/section-three-bgi.png b/public/img/haditha/mobile/section-three-bgi.png new file mode 100644 index 0000000..3b62cd3 Binary files /dev/null and b/public/img/haditha/mobile/section-three-bgi.png differ diff --git a/public/img/haditha/mobile/section-three-bgi_md.png b/public/img/haditha/mobile/section-three-bgi_md.png new file mode 100644 index 0000000..7f296b6 Binary files /dev/null and b/public/img/haditha/mobile/section-three-bgi_md.png differ diff --git a/public/img/haditha/mobile/section-three-bgi_sm.png b/public/img/haditha/mobile/section-three-bgi_sm.png new file mode 100644 index 0000000..3b62cd3 Binary files /dev/null and b/public/img/haditha/mobile/section-three-bgi_sm.png differ diff --git a/public/img/modal-bottom-left-bgi.png b/public/img/haditha/modal-bottom-left-bgi.png similarity index 100% rename from public/img/modal-bottom-left-bgi.png rename to public/img/haditha/modal-bottom-left-bgi.png diff --git a/public/img/haditha/modal-bottom-left-bgi.webp b/public/img/haditha/modal-bottom-left-bgi.webp new file mode 100644 index 0000000..525fa39 Binary files /dev/null and b/public/img/haditha/modal-bottom-left-bgi.webp differ diff --git a/public/img/modal-bttom-right-bgi.png b/public/img/haditha/modal-bttom-right-bgi.png similarity index 100% rename from public/img/modal-bttom-right-bgi.png rename to public/img/haditha/modal-bttom-right-bgi.png diff --git a/public/img/haditha/modal-bttom-right-bgi.webp b/public/img/haditha/modal-bttom-right-bgi.webp new file mode 100644 index 0000000..81ded2e Binary files /dev/null and b/public/img/haditha/modal-bttom-right-bgi.webp differ diff --git a/public/img/modal-top-bgi.png b/public/img/haditha/modal-top-bgi.png similarity index 100% rename from public/img/modal-top-bgi.png rename to public/img/haditha/modal-top-bgi.png diff --git a/public/img/haditha/modal-top-bgi.webp b/public/img/haditha/modal-top-bgi.webp new file mode 100644 index 0000000..f0470f3 Binary files /dev/null and b/public/img/haditha/modal-top-bgi.webp differ diff --git a/public/img/no-data.png b/public/img/haditha/no-data.png similarity index 100% rename from public/img/no-data.png rename to public/img/haditha/no-data.png diff --git a/public/img/haditha/robot-indicator.svg b/public/img/haditha/robot-indicator.svg new file mode 100644 index 0000000..1215d98 --- /dev/null +++ b/public/img/haditha/robot-indicator.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/img/sample-bgi.svg b/public/img/haditha/sample-bgi.svg similarity index 100% rename from public/img/sample-bgi.svg rename to public/img/haditha/sample-bgi.svg diff --git a/public/img/save.png b/public/img/haditha/save.png similarity index 100% rename from public/img/save.png rename to public/img/haditha/save.png diff --git a/public/img/haditha/section-four_card-five.png b/public/img/haditha/section-four_card-five.png new file mode 100644 index 0000000..aa9b704 Binary files /dev/null and b/public/img/haditha/section-four_card-five.png differ diff --git a/public/img/haditha/section-four_card-four.png b/public/img/haditha/section-four_card-four.png new file mode 100644 index 0000000..825e21e Binary files /dev/null and b/public/img/haditha/section-four_card-four.png differ diff --git a/public/img/haditha/section-four_card-one.png b/public/img/haditha/section-four_card-one.png new file mode 100644 index 0000000..5989bf0 Binary files /dev/null and b/public/img/haditha/section-four_card-one.png differ diff --git a/public/img/haditha/section-four_card-three.png b/public/img/haditha/section-four_card-three.png new file mode 100644 index 0000000..7ca408f Binary files /dev/null and b/public/img/haditha/section-four_card-three.png differ diff --git a/public/img/haditha/section-four_card-two.png b/public/img/haditha/section-four_card-two.png new file mode 100644 index 0000000..cf84d6b Binary files /dev/null and b/public/img/haditha/section-four_card-two.png differ diff --git a/public/img/haditha/section-three-bgi.png b/public/img/haditha/section-three-bgi.png new file mode 100644 index 0000000..4e45d9e Binary files /dev/null and b/public/img/haditha/section-three-bgi.png differ diff --git a/public/img/haditha/section-three-bgi.svg b/public/img/haditha/section-three-bgi.svg new file mode 100644 index 0000000..4c6fd5c --- /dev/null +++ b/public/img/haditha/section-three-bgi.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/img/haditha/section-three-bgi.webp b/public/img/haditha/section-three-bgi.webp new file mode 100644 index 0000000..a7ea6cd Binary files /dev/null and b/public/img/haditha/section-three-bgi.webp differ diff --git a/public/img/haditha/section-three-logo.png b/public/img/haditha/section-three-logo.png new file mode 100644 index 0000000..3e99c40 Binary files /dev/null and b/public/img/haditha/section-three-logo.png differ diff --git a/public/img/haditha/section-three-logo.svg b/public/img/haditha/section-three-logo.svg new file mode 100644 index 0000000..dc63f31 --- /dev/null +++ b/public/img/haditha/section-three-logo.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/img/sub-header-bgi.png b/public/img/haditha/sub-header-bgi.png similarity index 100% rename from public/img/sub-header-bgi.png rename to public/img/haditha/sub-header-bgi.png diff --git a/public/img/haditha/sub-header-bgi.webp b/public/img/haditha/sub-header-bgi.webp new file mode 100644 index 0000000..10f2b4f Binary files /dev/null and b/public/img/haditha/sub-header-bgi.webp differ diff --git a/public/img/save-2.png b/public/img/save-2.png deleted file mode 100644 index 76dfd68..0000000 Binary files a/public/img/save-2.png and /dev/null differ diff --git a/routes/chat.ts b/routes/chat.ts new file mode 100644 index 0000000..4d7958a --- /dev/null +++ b/routes/chat.ts @@ -0,0 +1,64 @@ +export default [ + { + path: "/chat", + file: "@chat/pages/index.vue", + children: [ + { + path: "", + redirect: { name: "unReads" }, + }, + { + path: "all/list", + name: "all", + file: "@chat/pages/Chat.vue", + meta: { + breadcrumb: "همه", + }, + }, + { + path: "privates/list", + name: "privates", + file: "@chat/pages/Chat.vue", + meta: { + breadcrumb: "خصوصی ها", + }, + }, + { + path: "groups/list", + name: "groups", + file: "@chat/pages/Chat.vue", + + meta: { + breadcrumb: "گروه ها", + }, + }, + { + path: "lobbies/list", + name: "lobbies", + file: "@chat/pages/Chat.vue", + + meta: { + breadcrumb: "تالارها", + }, + }, + { + path: "unreads/list", + name: "unReads", + file: "@chat/pages/Chat.vue", + + meta: { + breadcrumb: "نخوانده", + }, + }, + { + path: "my-messages/list", + name: "myMessages", + file: "@chat/pages/Chat.vue", + + meta: { + breadcrumb: "پیام های من", + }, + }, + ], + }, +]; diff --git a/routes/haditha.ts b/routes/haditha.ts new file mode 100644 index 0000000..69fda5e --- /dev/null +++ b/routes/haditha.ts @@ -0,0 +1,59 @@ +export default [ + { + name: "haditha", + path: "/haditha", + file: "~/systems/hadith_ui/pages/haditha/index.vue", + }, + { + name: "hadithaSearch", + path: "/haditha/search", + 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", + path: "/haditha/chat-bot", + file: "~/systems/hadith_ui/pages/haditha/chat-bot.vue", + }, + { + name: "hadithaFavorites", + path: "/haditha/favorites", + file: "~/systems/hadith_ui/pages/haditha/favorites/index.vue", + }, + { + name: "hadithaLibrary", + path: "/haditha/library", + file: "~/systems/hadith_ui/pages/haditha/library/index.vue", + }, + { + name: "hadithaLibraryShow", + path: "/haditha/library/:id/:slug?", + file: "~/systems/hadith_ui/pages/haditha/library/[id]/[slug]/index.vue", + }, + { + name: "hadithaAbout", + path: "/haditha/about-us", + file: "~/systems/hadith_ui/pages/haditha/public-pages/about-us.vue", + }, + { + name: "hadithaContact", + path: "/haditha/contact-us", + file: "~/systems/hadith_ui/pages/haditha/public-pages/contactus.vue", + }, + { + name: "hadithaRules", + path: "/haditha/rules", + file: "~/systems/hadith_ui/pages/haditha/public-pages/rules.vue", + }, + + { + name: "hadithaLogin", + path: "/haditha/login", + file: "~/systems/hadith_ui/pages/haditha/login.vue", + } +]; diff --git a/routes/research.ts b/routes/research.ts new file mode 100644 index 0000000..aad5db6 --- /dev/null +++ b/routes/research.ts @@ -0,0 +1,12 @@ +export default [ + { + name: "myResearches", + path: "/research/research-home", + file: "~/systems/research_ui/pages/index.vue", + }, + { + name: "TermPage", + path: "/research/research-term", + file: "~/systems/research_ui/pages/TermPage.vue", + }, +]; diff --git a/routes/search.ts b/routes/search.ts new file mode 100644 index 0000000..8aaeba3 --- /dev/null +++ b/routes/search.ts @@ -0,0 +1,37 @@ +export default [ + { + name: "search", + path: "/search", + file: "~/systems/search_ui/pages/search/index.vue", + }, + { + name: "searchNavigation", + path: "/search/lists", + file: "~/systems/search_ui/pages/search/lists.vue", + }, + { + name: "searchChart", + path: "/search/charts", + file: "~/systems/search_ui/pages/search/charts.vue", + }, + { + name: "showEntity", + path: "/search/:key/:id/show", + file: "~/systems/search_ui/pages/search/(show)/[key]/[id]/index.vue", + }, + { + name: "navigationView", + path: "/search/:key/:id/list", + file: "~/systems/search_ui/pages/search/(show)/[key]/[id]/index.vue", + }, + { + name: "entityResearch", + path: "/search/:key/:id/research", + file: "~/systems/search_ui/pages/search/(show)/[key]/[id]/index.vue", + }, + { + name: "entityResearch", + path: "/search/:key/:id/detail", + file: "~/systems/search_ui/pages/search/(show)/[key]/[id]/index.vue", + }, +]; diff --git a/server/api/upload.post.ts b/server/api/upload.post.ts new file mode 100644 index 0000000..4bae201 --- /dev/null +++ b/server/api/upload.post.ts @@ -0,0 +1,30 @@ +import { defineEventHandler, readMultipartFormData } from "h3"; +import { promises as fs } from "fs"; +import sharp from "sharp"; + +export default defineEventHandler(async (event) => { + const files = await readMultipartFormData(event); + + if (!files || files.length === 0) { + return { error: "No files uploaded" }; + } + + const uploadedFile = files[0]; + const fileName = `cropped-${Date.now()}.png`; + const filePath = `./public/uploads/${fileName}`; + + // Save the cropped image + await fs.writeFile(filePath, uploadedFile.data); + + // Optionally resize the image + const resizedFilePath = `./public/uploads/resized-${fileName}`; + await sharp(uploadedFile.data) + .resize(300, 300) // Adjust dimensions as needed + .toFile(resizedFilePath); + + return { + message: "File uploaded successfully", + originalFile: `/uploads/${fileName}`, + resizedFile: `/uploads/resized-${fileName}`, + }; +}); diff --git a/stores/authStore.ts b/stores/authStore.ts index 0654fd2..9a4a6d2 100644 --- a/stores/authStore.ts +++ b/stores/authStore.ts @@ -69,7 +69,7 @@ export const useAuthStore = defineStore("authStore", { isGuest(state) { return !state.isRealUser; }, - async isAuthenticatedGetter(state) { + isAuthenticatedGetter(state) { let isAuthenticated = useStorage("id_token", "GuestAccess").value; // updating value sample // isAuthenticated.value = null diff --git a/stores/commonStore.ts b/stores/commonStore.ts index 5034fef..59bf5e9 100644 --- a/stores/commonStore.ts +++ b/stores/commonStore.ts @@ -66,9 +66,7 @@ export const useCommonStore = defineStore("commonStore", { userLastState: null, schemas: {} as Schemas, activeSchema: {} as ActiveSchema, - forwardItem: {} as ForwardItem, selectedlists: {} as Selectedlists, - sidebarListStatus: false, userHistory: {}, lastRecord: {} as lastRecord | undefined, @@ -122,7 +120,6 @@ export const useCommonStore = defineStore("commonStore", { repoMircroServiceName: () => import.meta.env.VITE_REPO, logMircroServiceName: () => import.meta.env.VITE_LOG, listMircroServiceName: () => import.meta.env.VITE_LIST, - getForwardItem: (state) => state.forwardItem, activeSchemaGetter: (state) => state.activeSchema, schemasGetter: (state) => state.schemas, organNameGetter: () => import.meta.env.VITE_BUILD_NAME, @@ -142,7 +139,6 @@ export const useCommonStore = defineStore("commonStore", { isDesktopGetter: (state) => state.isDesktop, isMobileGetter: (state) => state.isMobile, selectedlistsGetter: (state) => state.selectedlists, - sidebarListStatusGetter: (state) => state.sidebarListStatus, sidebarMenuGetter: (state) => state.sidebarMenu, userHistoryGetter: (state) => state.userHistory, lastRecordGetter: (state) => state.lastRecord, @@ -189,9 +185,7 @@ export const useCommonStore = defineStore("commonStore", { this.collapsed = isCollapsed; }, - SET_FORWARD_ITEM(forwardItem: ForwardItem) { - this.forwardItem = forwardItem; - }, + SET_SECTIONS(jahatSection: JahatSection) { this.jahatSection = jahatSection; }, @@ -232,12 +226,6 @@ export const useCommonStore = defineStore("commonStore", { this.selectedlists = selectedlists; }, - // SET_SIDEBAR_LIST_STATUS(newState = undefined) { - // this.sidebarListStatus = - // newState != undefined || newState != null - // ? newState - // : !this.sidebarListStatus; - // }, SET_AUTHORIZED_PAGES(pages: Permission[] = []) { const AuthorizedPages: Set = new Set(); @@ -266,14 +254,7 @@ export const useCommonStore = defineStore("commonStore", { clearUser() { this.$reset(); }, - chatSidebarListStatusReactor(newState: boolean) { - // this.SET_SIDEBAR_LIST_STATUS = newVal; - - this.sidebarListStatus = - newState != undefined || newState != null - ? newState - : !this.sidebarListStatus; - }, + async getState() { const settingsApi = (await import("~/apis/adminApi")).default; diff --git a/tailwind.config.js b/tailwind.config.js index fee7a5f..00c74c1 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,24 +1,32 @@ module.exports = { - prefix: 'tw-', + prefix: "tw-", + content: [ + "./components/**/*.{js,vue,ts}", + "./layouts/**/*.vue", + "./pages/**/*.vue", + "./plugins/**/*.{js,ts}", + "./nuxt.config.{js,ts}", + ], + theme: { + screens: { + sm: "360px", + md: "720px", + lg: "992px", + xl: "1200px", + "2xl": "1400px", + "3xl": "1900px", + }, + extend: {}, + }, + plugins: [], + purge: { + enabled: process.env.NODE_ENV === "production", content: [ - './components/**/*.{js,vue,ts}', - './layouts/**/*.vue', - './pages/**/*.vue', - './plugins/**/*.{js,ts}', - './nuxt.config.{js,ts}', + "./components/**/*.{js,vue,ts}", + "./layouts/**/*.vue", + "./pages/**/*.vue", + "./plugins/**/*.{js,ts}", + "./nuxt.config.{js,ts}", ], - theme: { - extend: {}, - }, - plugins: [], - purge: { - enabled: process.env.NODE_ENV === 'production', - content: [ - './components/**/*.{js,vue,ts}', - './layouts/**/*.vue', - './pages/**/*.vue', - './plugins/**/*.{js,ts}', - './nuxt.config.{js,ts}', - ], - }, - }; \ No newline at end of file + }, +}; diff --git a/utils/globalMixin.ts b/utils/globalMixin.ts index 7aa312d..9b151af 100644 --- a/utils/globalMixin.ts +++ b/utils/globalMixin.ts @@ -4,6 +4,7 @@ import { convertEnToPe } from "~/manuals/persianNumber"; // import Cookies from "js-cookie"; import { useCommonStore } from "~/stores/commonStore"; import { useAuthStore } from "~/stores/authStore"; +import { isValidHttpUrl } from "~/manuals/utilities"; // // ...mapState("common", ["activeSystemGetter"]), export const appDescription = () => { @@ -168,6 +169,8 @@ export const copyToClipboard = async ( id = undefined, domainUrl = undefined ) => { + const toast = useToast(); + try { const _id = id ? "/" + id : ""; let url = location.href; @@ -176,27 +179,37 @@ export const copyToClipboard = async ( } await navigator.clipboard.writeText(url + _id); - mySwalToast({ - html: "نشانی پیوند کپی شد.", + toast.add({ + title: "انجام شد.", + description: "نشانی پیوند کپی شد.", + color: "success", }); } catch (err) { console.log(err.message); - mySwalToast({ - html: "خطایی رخ داد.لطفا دوباره امتحان کنید.", + toast.add({ + title: "انجام شد.", + description: "خطایی رخ داد.لطفا دوباره امتحان کنید.", + color: "error", }); } }; export const copyTextToClipboard = async (text) => { + const toast = useToast(); + try { await navigator.clipboard.writeText(text); - mySwalToast({ - html: "متن کپی شد.", + toast.add({ + title: "انجام شد.", + description: "متن کپی شد.", + color: "success", }); } catch (err) { console.log(err.message); - mySwalToast({ - html: "خطایی رخ داد.لطفا دوباره امتحان کنید.", + toast.add({ + title: "انجام شد.", + description: "خطایی رخ داد.لطفا دوباره امتحان کنید.", + color: "error", }); } }; @@ -274,7 +287,7 @@ export const userAvatar = (user = undefined) => { if (user?.avatar && user?.avatar?.length) { return ( import.meta.env.VITE_BASE_URL + - import.meta.env.VITE_API_NAME + + import.meta.env.NUXT_PUBLIC_API_NAME + fileUrl() + user.avatar ); @@ -347,7 +360,7 @@ export const redirectToRouteName = (routeName = "dashboard") => { // clearBodyClass(); }); }; -export const getGroupAvatar = (user = undefined) => { +export const getGroupAvatar = async (user = undefined) => { try { if (user) { if (isValidHttpUrl(user.avatar)) return user.avatar; @@ -361,11 +374,11 @@ export const getGroupAvatar = (user = undefined) => { const initials = nameArray[0].charAt(0); 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) { - return import("~/assets/common/img/default.svg").default; + return (await import("~/assets/common/img/default.svg")).default; } }; export const convertUnixToPersianDateTime = (created_at) => { diff --git a/utils/useApi.ts b/utils/useApi.ts index 6d26c99..51ec60b 100644 --- a/utils/useApi.ts +++ b/utils/useApi.ts @@ -4,7 +4,7 @@ export async function useAPI( url: string | (() => string), options?: UseFetchOptions ) { - const prexFixUrlWithApiName = import.meta.env.VITE_API_NAME + url; + const prexFixUrlWithApiName = import.meta.env.NUXT_PUBLIC_API_NAME+ url; return await useFetch(prexFixUrlWithApiName, { ...options, diff --git a/yarn.lock b/yarn.lock index d745e13..37c5205 100644 --- a/yarn.lock +++ b/yarn.lock @@ -766,6 +766,20 @@ resolved "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz" integrity sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA== +"@iconify-json/lucide@^1.2.28": + version "1.2.28" + resolved "https://registry.npmjs.org/@iconify-json/lucide/-/lucide-1.2.28.tgz" + integrity sha512-SPeAoh1YKhALpNSto/FBspf3GZ0eAr3ka/OI7cJJ5HljLzycIITv0s4Rd2+sRVzFtD1I991mJJmYohQeOSZ+Og== + dependencies: + "@iconify/types" "*" + +"@iconify-json/vscode-icons@^1.2.16": + version "1.2.16" + resolved "https://registry.npmjs.org/@iconify-json/vscode-icons/-/vscode-icons-1.2.16.tgz" + integrity sha512-hstc2yVq2UJ6v6FrgjftzXRvphGZBsKxvSeXoFLP1Hgx89TPZKrGE5SV6vqsoeIlLYaQ7OZbXmAoVGroTfGmVQ== + dependencies: + "@iconify/types" "*" + "@iconify/collections@^1.0.496": version "1.0.516" resolved "https://registry.npmjs.org/@iconify/collections/-/collections-1.0.516.tgz" @@ -3260,6 +3274,11 @@ bluebird@~3.4.0: resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz" integrity sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA== +blueimp-canvas-to-blob@^3.14.0: + version "3.29.0" + resolved "https://registry.npmjs.org/blueimp-canvas-to-blob/-/blueimp-canvas-to-blob-3.29.0.tgz" + integrity sha512-0pcSSGxC0QxT+yVkivxIqW0Y4VlO2XSDPofBAqoJ1qJxgH9eiUDLv50Rixij2cDuEfx4M6DpD9UGZpRhT5Q8qg== + boolbase@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz" @@ -3622,7 +3641,7 @@ cluster-key-slot@^1.1.0: cmd-shim@^7.0.0: version "7.0.0" -codemirror@6.x: +codemirror@^6.0.1, codemirror@6.x: version "6.0.1" resolved "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz" integrity sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg== @@ -3842,6 +3861,14 @@ cronstrue@^2.52.0: resolved "https://registry.npmjs.org/cronstrue/-/cronstrue-2.54.0.tgz" integrity sha512-vyp5NklDxA5MjPfQgkn0bA+0vRQe7Q9keX7RPdV6rMgd7LtDvbuKgnT+3T5ZAX16anSP5HmahcRp8mziXsLfaw== +cropperjs@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/cropperjs/-/cropperjs-2.0.0.tgz" + integrity sha512-TO2j0Qre01kPHbow4FuTrbdEB4jTmGRySxW49jyEIqlJZuEBfrvCTT0vC3eRB2WBXudDfKi1Onako6DKWKxeAQ== + dependencies: + "@cropper/elements" "^2.0.0" + "@cropper/utils" "^2.0.0" + cross-fetch@^3.0.4: version "3.2.0" resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz" @@ -6310,6 +6337,16 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +lucide-vue-next@^0.477.0: + version "0.477.0" + resolved "https://registry.npmjs.org/lucide-vue-next/-/lucide-vue-next-0.477.0.tgz" + integrity sha512-C7azIKO7aJKf5MD7OIzV7NRDtnjXH3KSXfyJgGqRIMemuMzW/9esuMxDXIXDhBZcJgRtXMUN0FcJwOJZQ8SywA== + +lucide@^0.477.0: + version "0.477.0" + resolved "https://registry.npmjs.org/lucide/-/lucide-0.477.0.tgz" + integrity sha512-lEgt1ni9sKohbLsYWSnM3mKVRkvUrJ3Ijj01RAdM5F0iyvxkCcy3gPrb1G2ux6zE4y20ptcitfMa0OOFXI57gw== + magic-regexp@^0.8.0: version "0.8.0" resolved "https://registry.npmjs.org/magic-regexp/-/magic-regexp-0.8.0.tgz" @@ -9969,6 +10006,14 @@ vue-i18n@*, vue-i18n@^10.0.0, vue-i18n@^10.0.1, vue-i18n@^10.0.3: "@intlify/shared" "10.0.4" "@vue/devtools-api" "^6.5.0" +vue-image-upload-resize@^2.3.0: + version "2.3.0" + resolved "https://registry.npmjs.org/vue-image-upload-resize/-/vue-image-upload-resize-2.3.0.tgz" + integrity sha512-ElzyAVCluiDt8xSZkSK9FbuLY5mr23JlO4cHyyRo86RfEGLWtvXrTq7vYOgDstT8rNBmnTgNCkPKc0rpmyl1yA== + dependencies: + blueimp-canvas-to-blob "^3.14.0" + vue "^2.5.17" + vue-jalali-moment@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/vue-jalali-moment/-/vue-jalali-moment-1.0.0.tgz" @@ -10389,6 +10434,11 @@ zip-stream@^6.0.1: compress-commons "^6.0.2" readable-stream "^4.0.0" +zod@^3.24.2: + version "3.24.2" + resolved "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz" + integrity sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ== + zrender@5.6.0: version "5.6.0" resolved "https://registry.npmjs.org/zrender/-/zrender-5.6.0.tgz"