Compare commits

..

No commits in common. "main" and "baghi/baseui/refactor" have entirely different histories.

118 changed files with 821 additions and 2241 deletions

View File

@ -1,5 +1,5 @@
NUXT_PUBLIC_API_NAME=api/
NUXT_PUBLIC_BASE_URL=http://192.168.23.60/
VITE_API_NAME=api/
VITE_BASE_URL=http://192.168.23.60/
VITE_APP_NAME=Hadith
@ -7,9 +7,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=haditha
VITE_BUILD_NAME=hadith
VITE_IDB_NAME=haditha
VITE_IDB_NAME=hadith
VITE_IDB_VERSION=1
VITE_ENABLE_IDB=1

3
.gitmodules vendored
View File

@ -7,6 +7,3 @@
[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

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

@ -1,52 +0,0 @@
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 <repository-url>
cd <repository-directory>
git submodule init
git submodule update
Or, you can do it in one step:
git clone --recurse-submodules <repository-url>
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 <path-to-submodule>.
3. Delete the submodule directory: rm -rf <path-to-submodule>.
4. Stage the .gitmodules changes: git add .gitmodules.
5. Commit the changes: git commit -m "Removed submodule <submodule-name>".
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 <hash> 0 <path>)
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://github.com/example/repo.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

68
app.vue
View File

@ -2,48 +2,58 @@
<UApp :locale="fa_ir">
<NuxtLoadingIndicator />
<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>
<!-- this component will be rendered on client-side -->
<!-- <NuxtClientFallback
fallback-tag="span"
fallback="NuxtClientFallback"
@ssr-error="logSomeError"
> -->
<NuxtPage />
<!-- <BrokeInSsr /> -->
<!-- </NuxtClientFallback> -->
</NuxtLayout>
</UApp>
</template>
<script setup lang="ts">
import { fa_ir } from "@nuxt/ui/locale";
onMounted(() => {
// const toast = useToast();
// toast.add({
// title: "hello world",
// });
});
// import { useCounterStore } from "~/stores/counter";
// import { storeToRefs } from "pinia";
// export default {
// setup() {
// definePageMeta({
// colorMode: "light",
// });
// },
// mounted() {
// access the `store` variable anywhere in the component
// const store = useCounterStore();
// const { count, doubleCount } = storeToRefs(store);
// const { increment } = store;
// console.info(this.$config.public.TAHRIR_ASSETS_URL);
// console.info(this.$config.public.PUBLIC_JAHAT_ASSETS_URL);
// console.info(this.$config.public.VITE_APP_NAME);
// console.info(import.meta.env.VITE_APP_NAME);
// console.info(this.$config.public);
// console.info(this.$config.public.TITLE);
// console.info(this.$config.public.NODE_ENV);
// console.info(this.$config.public.VITE_APP_NAME);
// console.info(this.$config.public.VITE_BASE_URL);
// console.info(this.$config.public.VITE_BASE_URL);
// },
// setup() {
// definePageMeta({
// colorMode: "light",
// });
// },
// mounted() {
// access the `store` variable anywhere in the component
// const store = useCounterStore();
// const { count, doubleCount } = storeToRefs(store);
// const { increment } = store;
// console.info(this.$config.public.TAHRIR_ASSETS_URL);
// console.info(this.$config.public.PUBLIC_JAHAT_ASSETS_URL);
// console.info(this.$config.public.VITE_APP_NAME);
// console.info(import.meta.env.VITE_APP_NAME);
// console.info(this.$config.public);
// console.info(this.$config.public.TITLE);
// console.info(this.$config.public.NODE_ENV);
// console.info(this.$config.public.VITE_APP_NAME);
// console.info(this.$config.public.VITE_BASE_URL);
// console.info(this.$config.public.VITE_BASE_URL);
// },
// methods: {
// logSomeError(error) {
// console.info("logSomeError", error);

View File

@ -60,6 +60,3 @@
// responsive
@import "responsive/responsive";
// @import "tailwindcss";
// @import "@nuxt/ui";

View File

@ -59,6 +59,3 @@
// responsive
@import "responsive/responsive";
// @import "tailwindcss";
// @import "@nuxt/ui";

View File

@ -1,7 +1,5 @@
// @import "src/assets/common/scss/mixin";
// @import "src/assets/common/scss/placeholder";
@import "@/assets/common/scss/mixin";
@import "@/assets/common/scss/placeholder";
@import "src/assets/common/scss/mixin";
@import "src/assets/common/scss/placeholder";
.admin-system,.task-system,.admin-panel{
//@import "main";

View File

@ -1,7 +1,5 @@
// @import "src/assets/common/scss/mixin";
// @import "src/assets/common/scss/placeholder";
@import "@/assets/common/scss/mixin";
@import "@/assets/common/scss/placeholder";
@import "src/assets/common/scss/mixin";
@import "src/assets/common/scss/placeholder";
.admin-panel {
.pages-content-container {

View File

@ -106,9 +106,7 @@
<script>
import authMixin from "~/mixins/authMixin";
import { required,minLength } from '@vuelidate/validators'
import useVuelidate from '@vuelidate/core'
import { required, minLength } from "vuelidate/lib/validators";
import { mapState } from "pinia";

View File

@ -5,13 +5,13 @@
"{{ userFullname(getFullName) }}" عزیز، خوش آمدید.
</div>
<div v-else>0{{ getMobile }}</div>
<div v-else> 0{{ getMobile }} </div>
</div>
<div class="m-sign-up__text">رمز پیامک شده را وارد کنید</div>
<div class="m-sign-up__form">
<div class="m-sign-up__form-row m-sign-up__simple-input">
<div
class="form-group"
class="form-group "
:class="{ 'form-group--error': $v.code.$error }"
>
<input
@ -106,8 +106,7 @@
<script>
import authMixin from "~/mixins/authMixin";
import { required, minLength } from "@vuelidate/validators";
import { required, minLength } from "vuelidate/lib/validators";
import { useCommonStore } from "~/stores/commonStore";
import { useAuthStore } from "~/stores/authStore";
import { mapState } from "pinia";
@ -148,11 +147,7 @@ export default {
};
},
computed: {
...mapState(useAuthStore, [
"getMobile",
"getFullName",
"getResetPasswordState",
]),
...mapState(useAuthStore,["getMobile", "getFullName", "getResetPasswordState"]),
},
methods: {
resetErrors() {
@ -192,7 +187,7 @@ export default {
const { $eventBus } = useNuxtApp();
$eventBus.emit(
"authenticated-by-modal",
'authenticated-by-modal',
this.$route.query["invite-id"]
);
@ -231,7 +226,7 @@ export default {
const vm = this;
var timeleft = timeInSecond;
var downloadTimer = setInterval(function () {
var downloadTimer = setInterval(function() {
if (timeleft <= 0) {
clearInterval(downloadTimer);
vm.$refs.countdown.innerHTML = "ارسال مجدد";
@ -255,7 +250,7 @@ export default {
display: inline-block !important;
text-align: center !important;
border: none !important;
background: unset !important;
background:unset !important;
&[disabled] {
min-width: 4em !important;
}

View File

@ -43,7 +43,7 @@ import {
minLength,
maxLength,
between,
} from "@vuelidate/validators";
} from "vuelidate/lib/validators";
export default {
name: "forget",

View File

@ -156,7 +156,7 @@ import {
minLength,
maxLength,
between,
} from "@vuelidate/validators";
} from "vuelidate/lib/validators";
export default {
mounted() {

View File

@ -116,7 +116,7 @@ import {
minLength,
maxLength,
between,
} from "@vuelidate/validators";
} from "vuelidate/lib/validators";
import { mapState, mapActions } from "pinia";
import { useCommonStore } from "~/stores/commonStore";

View File

@ -207,7 +207,7 @@ import {
maxLength,
between,
sameAs,
} from "@vuelidate/validators";
} from "vuelidate/lib/validators";
export default {
mounted(){

View File

@ -93,7 +93,7 @@ import {
maxLength,
between,
sameAs,
} from "@vuelidate/validators";
} from "vuelidate/lib/validators";
export default {
validations: {

View File

@ -110,7 +110,7 @@ import {
required,
minLength,
sameAs,
} from "@vuelidate/validators";
} from "vuelidate/lib/validators";
import { mapState, mapActions } from "pinia";
import { useCommonStore } from "~/stores/commonStore";
import { useAuthStore } from "~/stores/authStore";

View File

@ -34,8 +34,12 @@
<script>
import authMixin from "~/mixins/authMixin";
import { required, minLength, maxLength, between } from "@vuelidate/validators";
import {
required,
minLength,
maxLength,
between,
} from "vuelidate/lib/validators";
export default {
name: "forget",

View File

@ -116,7 +116,7 @@ import {
minLength,
maxLength,
between,
} from "@vuelidate/validators";
} from "vuelidate/lib/validators";
import { mapState, mapActions } from "pinia";
import { useCommonStore } from "~/stores/commonStore";

View File

@ -146,7 +146,7 @@ import {
maxLength,
between,
sameAs,
} from "@vuelidate/validators";
} from "vuelidate/lib/validators";
export default {
validations: {

View File

@ -107,7 +107,7 @@ import {
required,
minLength,
sameAs,
} from "@vuelidate/validators";
} from "vuelidate/lib/validators";
import { mapState, mapActions } from "pinia";
export default {

View File

@ -44,7 +44,7 @@ import {
minLength,
maxLength,
between,
} from "@vuelidate/validators";
} from "vuelidate/lib/validators";
export default {
validations: {

View File

@ -63,8 +63,8 @@
<div class="row">
<div class="col-sm-6 mb-2 mb-sm-0 col-md mb-sm-2 mb-md-0">
<div class="link-item-container">
<NuxtLink
:to="urlResolver('qq309202')"
<a
:href="urlResolver('qq309202')"
target="_blank"
class="btn link-item"
>
@ -80,13 +80,13 @@
<div class="more-text-container">
<span class="more-text"> مشاهده بیشتر </span>
</div>
</NuxtLink>
</a>
</div>
</div>
<div class="col-sm-6 mb-2 mb-sm-0 col-md mb-sm-2 mb-md-0">
<div class="link-item-container">
<NuxtLink
:to="urlResolver('qq308235')"
<a
:href="urlResolver('qq308235')"
target="_blank"
class="btn link-item"
>
@ -100,13 +100,13 @@
<div class="more-text-container">
<span class="more-text"> مشاهده بیشتر </span>
</div>
</NuxtLink>
</a>
</div>
</div>
<div class="col-sm-6 mb-2 mb-sm-0 col-md">
<div class="link-item-container">
<NuxtLink
:to="urlResolver('qq38162')"
<a
:href="urlResolver('qq38162')"
target="_blank"
class="btn link-item"
>
@ -120,13 +120,13 @@
<div class="more-text-container">
<span class="more-text"> مشاهده بیشتر </span>
</div>
</NuxtLink>
</a>
</div>
</div>
<div class="col-sm-6 mb-2 mb-sm-0 col-md">
<div class="link-item-container">
<NuxtLink
:to="urlResolver('qq233930')"
<a
:href="urlResolver('qq233930')"
target="_blank"
class="btn link-item"
>
@ -140,7 +140,7 @@
<div class="more-text-container">
<span class="more-text"> مشاهده بیشتر </span>
</div>
</NuxtLink>
</a>
</div>
</div>
</div>
@ -156,8 +156,7 @@ import searchApi from "~/apis/searchApi";
import { mapState, mapActions } from "pinia";
import { useCommonStore } from "~/stores/commonStore";
import { useStorage } from "@vueuse/core";
import { clearBodyClass } from "@manuals/utilities";
import { useRouter } from "vue-router";
import {clearBodyClass} from "@manuals/utilities"
export default {
beforeMount() {
@ -165,7 +164,7 @@ export default {
},
mounted() {
this.setBodyClass("majles-user-panel");
let localStoageSearchSchema = useStorage("searchSchema", undefined).value;
let localStoageSearchSchema = useStorage("searchSchema",undefined).value;
if (localStoageSearchSchema) {
let searchSchema = JSON.parse(localStoageSearchSchema);
this.schemasSetter(searchSchema);
@ -256,9 +255,7 @@ export default {
},
urlResolver(_id) {
const router = `search/qasection/${_id}/show`;
return router;
return "";
// const routeData = this.$router.resolve({
// path: "navigation",
// params: {
@ -275,6 +272,7 @@ export default {
<style lang="scss">
@import "../../../assets/majles/scss/majles";
.custom-class {
.dropdown-toggle {
color: rgba(0, 0, 0, 0.5) !important;

View File

@ -4,7 +4,7 @@
>{{ getLabel() }}:</label
>
<div>
<!-- <codemirror
<codemirror
:options="cmOptions"
class="markdown-preview"
v-model="textValue"
@ -12,7 +12,7 @@
:id="localFormElement.key"
:name="localFormElement.key"
ref="myCm"
></codemirror> -->
></codemirror>
</div>
</div>
</template>
@ -21,20 +21,20 @@
import { mapState } from "pinia";
import formBuilderMixin from "@mixins/formBuilderMixin";
// import { codemirror } from "vue-codemirror";
// import "vue-codemirror/node_modules/codemirror/lib/codemirror.css";
// import "vue-codemirror/node_modules/codemirror/mode/markdown/markdown.js";
// import "vue-codemirror/node_modules/codemirror/mode/javascript/javascript.js";
// import "vue-codemirror/node_modules/codemirror/mode/css/css.js";
// import "vue-codemirror/node_modules/codemirror/mode/vue/vue.js";
// import "vue-codemirror/node_modules/codemirror/mode/htmlmixed/htmlmixed.js";
// import "vue-codemirror/node_modules/codemirror/addon/edit/closebrackets.js";
// import "vue-codemirror/node_modules/codemirror/addon/edit/matchbrackets.js";
// import "vue-codemirror/node_modules/codemirror/addon/edit/closetag.js";
// import "vue-codemirror/node_modules/codemirror/addon/display/placeholder.js";
// import "vue-codemirror/node_modules/codemirror/addon/scroll/simplescrollbars.js";
// import "vue-codemirror/node_modules/codemirror/addon/scroll/simplescrollbars.css";
// import "vue-codemirror/node_modules/codemirror/addon/selection/active-line.js";
import { codemirror } from "vue-codemirror";
import "vue-codemirror/node_modules/codemirror/lib/codemirror.css";
import "vue-codemirror/node_modules/codemirror/mode/markdown/markdown.js";
import "vue-codemirror/node_modules/codemirror/mode/javascript/javascript.js";
import "vue-codemirror/node_modules/codemirror/mode/css/css.js";
import "vue-codemirror/node_modules/codemirror/mode/vue/vue.js";
import "vue-codemirror/node_modules/codemirror/mode/htmlmixed/htmlmixed.js";
import "vue-codemirror/node_modules/codemirror/addon/edit/closebrackets.js";
import "vue-codemirror/node_modules/codemirror/addon/edit/matchbrackets.js";
import "vue-codemirror/node_modules/codemirror/addon/edit/closetag.js";
import "vue-codemirror/node_modules/codemirror/addon/display/placeholder.js";
import "vue-codemirror/node_modules/codemirror/addon/scroll/simplescrollbars.js";
import "vue-codemirror/node_modules/codemirror/addon/scroll/simplescrollbars.css";
import "vue-codemirror/node_modules/codemirror/addon/selection/active-line.js";
export default {
mixins: [formBuilderMixin],

View File

@ -1,8 +1,8 @@
<template>
<div class="row form-group" :key="$attrs.key">
<label :for="localFormElement?.key" class="col-md-3"
>{{ localFormElement?.label }}:</label
>
<label :for="localFormElement?.key" class="col-md-3">{{
localFormElement?.label
}}:</label>
<div v-if="isInitial" class="dropbox">
<input
@ -57,8 +57,8 @@ const STATUS_INITIAL = 0,
STATUS_SUCCESS = 2,
STATUS_FAILED = 3;
// import { upload } from "@services/fileUploadService.js";
import { wait } from "~/manuals/utilities.js";
import { upload } from "@services/fileUploadService";
import { wait } from "@utilities/utilities.js";
import formBuilderMixin from "@mixins/formBuilderMixin";
export default {
@ -107,16 +107,16 @@ export default {
// upload data to the server
this.currentStatus = STATUS_SAVING;
// upload(formData)
// .then(wait(1500)) // DEV ONLY: wait for 1.5s
// .then((x) => {
// this.uploadedFiles = [].concat(x);
// this.currentStatus = STATUS_SUCCESS;
// })
// .catch((err) => {
// this.uploadError = err.response;
// this.currentStatus = STATUS_FAILED;
// });
upload(formData)
.then(wait(1500)) // DEV ONLY: wait for 1.5s
.then((x) => {
this.uploadedFiles = [].concat(x);
this.currentStatus = STATUS_SUCCESS;
})
.catch((err) => {
this.uploadError = err.response;
this.currentStatus = STATUS_FAILED;
});
},
reset() {
// reset form to initial state

View File

@ -92,7 +92,7 @@ export default {
// datePicker: VuePersianDatetimePicker,
datePicker: () =>
import(
"vue3-persian-datetime-picker"
"vue-persian-datetime-picker"
),
},
};

View File

@ -30,15 +30,13 @@
<script>
import formBuilderMixin from "@mixins/formBuilderMixin";
// import HttpService from "@services/httpService";
import HttpService from "@services/httpService";
export default {
// props:["listOptions"],
mixins: [formBuilderMixin],
created() {
this.httpService = useNuxtApp()["$http"];
},
mounted() {
setTimeout(() => {
this.setOptions();
@ -47,7 +45,7 @@ export default {
},
data() {
return {
httpService: {},
httpService: undefined,
optionRendering: false,
listOptions: [],
};
@ -175,7 +173,7 @@ export default {
if (this.optionRendering) return;
let vm = this;
// this.httpService = new HttpService();
this.httpService = new HttpService();
this.optionRendering = true;

View File

@ -1,5 +1,4 @@
<template>
<client-only>
<aside
class="nav-sidebar"
:class="[
@ -69,10 +68,7 @@
</span>
</NuxtLink>
<ul
class="sidebar-sub-level-items li-child"
:id="item.link"
>
<ul class="sidebar-sub-level-items li-child" :id="item.link">
<li class="fly-out-top-item active gl-link">
<span class="fly-out-top-item-container">
<strong class="fly-out-top-item-name">
@ -211,14 +207,8 @@
@mouseleave="emitCustomEvent($event, 'out')"
>
<a class="has-sub-items gl-link">
<svg
v-if="isGuest && showRegister"
class="icon icon-personal"
>
<use
class="icon-personal"
xlink:href="#icon-personal"
></use>
<svg v-if="isGuest && showRegister" class="icon icon-personal">
<use class="icon-personal" xlink:href="#icon-personal"></use>
</svg>
<img
v-else
@ -348,7 +338,6 @@
<SvgIconComponent></SvgIconComponent>
</aside>
</client-only>
</template>
<script>
import { mapState, mapActions } from "pinia";

View File

@ -1,80 +0,0 @@
<template>
<div>
<input type="file" accept="image/*" @change="onFileChange" />
<div v-if="imageSrc" class="cropper-container">
<img ref="image" :src="imageSrc" alt="Image to crop" />
</div>
<button v-if="imageSrc" @click="cropImage">Crop and Upload</button>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import Cropper from 'cropperjs';
import 'cropperjs/dist/cropper.css';
const imageSrc = ref(null);
const image = ref(null);
let cropper = null;
const onFileChange = (e) => {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = (event) => {
imageSrc.value = event.target.result;
initCropper();
};
reader.readAsDataURL(file);
}
};
const initCropper = () => {
if (cropper) {
cropper.destroy();
}
cropper = new Cropper(image.value, {
aspectRatio: 1, // Set aspect ratio (e.g., 1 for square)
viewMode: 1, // Restrict the crop box to the size of the image
});
};
const cropImage = () => {
if (cropper) {
const croppedCanvas = cropper.getCroppedCanvas();
croppedCanvas.toBlob((blob) => {
uploadImage(blob);
});
}
};
const uploadImage = async (blob) => {
const formData = new FormData();
formData.append('image', blob, 'cropped-image.png');
try {
const response = await $fetch('/api/upload', {
method: 'POST',
body: formData,
});
alert('Image uploaded successfully!');
console.log('Upload response:', response);
} catch (error) {
console.error('Error uploading image:', error);
alert('Error uploading image');
}
};
onBeforeUnmount(() => {
if (cropper) {
cropper.destroy();
}
});
</script>
<style scoped>
.cropper-container {
max-width: 100%;
margin-top: 20px;
}
</style>

View File

@ -86,13 +86,13 @@ import repoApi from "~/apis/repoApi";
import { mapState } from "pinia";
import { useCommonStore } from "~/stores/commonStore";
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";
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";
/**
* @vue-data {Object} [listUpdatedText = {}] - متنهای بهروزشده در لیست.
* @vue-data {undefined} [httpService = undefined] - سرویس HTTP برای درخواستها.

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

@ -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);
}
}

View File

@ -0,0 +1,17 @@
<script setup>
import { clearBodyClass } from "@manuals/utilities";
onMounted(() => {
clearBodyClass();
});
onUnmounted(() => {
clearBodyClass();
});
</script>
<template>
<main class="h-full">
<slot name="named-slot"></slot>
<slot></slot>
</main>
</template>

View File

@ -1,9 +1,8 @@
<!-- layouts/default.vue -->
<template>
<div>
<!-- //////////////////// begin navbar //////////////////// -->
<template v-if="$attrs.showNavbar">
<header v-if="buildName() != 'majles'">
<!-- //////////////////// begin navbar //////////////////// -->
<nav
class="navbar navbar-expand-md navbar-light bg-light"
:class="{ expanded: !isSidebarCollapsed }"
@ -29,8 +28,8 @@
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
data-toggle="collapse"
data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
@ -51,10 +50,10 @@
</div>
<button
class="btn p-0 me-auto"
class="btn p-0 mr-auto"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
data-toggle="collapse"
data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
@ -64,7 +63,7 @@
</svg>
</button>
</div>
<ul class="navbar-nav ms-auto me-md-5">
<ul class="navbar-nav ml-auto mr-md-5">
<!-- <li class="nav-item active">
<a class="nav-link" href="#"
>پیشخوان <span class="sr-only">(current)</span></a
@ -78,7 +77,7 @@
class="nav-link dropdown-toggle"
id="navbarDropdown"
role="button"
data-bs-toggle="dropdown"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
@ -94,7 +93,7 @@
href="#"
id="navbarDropdown"
role="button"
data-bs-toggle="dropdown"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
@ -129,7 +128,7 @@
</li>
</ul>
<ul class="navbar-nav ms-md-3 me-auto">
<ul class="navbar-nav ml-md-3 mr-auto">
<li class="nav-item">
<notification></notification>
</li>
@ -146,32 +145,23 @@
</ul>
</div>
</nav>
</header>
</template>
<!-- //////////////////// end navbar //////////////////// -->
</header>
<!-- <the-sidebar :showUserAvatar="true" :menu="menu"></the-sidebar> -->
<the-sidebar
:showUserAvatar="true"
:menu="$attrs.menu"
@statusPag="statusPag"
></the-sidebar>
<client-only>
<main
class="main-page__content"
:class="{ expanded: !isSidebarCollapsed }"
>
<main class="main-page__content" :class="{ expanded: !isSidebarCollapsed }">
<!-- <div class="pages list-page"> -->
<!-- <div class="pages-content align-items-stretch p-0"> -->
<!-- <div class="flex-grow-1"> -->
<slot></slot>
<!-- </div> -->
<!-- </div> -->
<!-- </div> -->
</main>
</client-only>
</div>
</template>
@ -179,7 +169,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");

View File

@ -1,4 +1,4 @@
// middleware/redirect.js
export default defineNuxtRouteMiddleware((to, from) => {
if (buildName() == "haditha" && to.path == '/') return navigateTo({ name: "haditha" });
if (buildName() == "hadith" && to.path == '/') return navigateTo({ name: "hadith" });
});

View File

@ -33,8 +33,6 @@ export default {
]),
// callFrom : page | modal
async authBase(methodName, callFrom = "page") {
const toast = useToast();
// this.$v.$touch();
const route = useRoute();
const router = useRouter();
@ -53,19 +51,16 @@ export default {
this[methodName]()
.then((res) => {
toast.add({
title: res.message,
icon: "success",
timer: 2000,
});
// mySwalToast({
// 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 {
@ -86,12 +81,10 @@ export default {
}
})
.catch((err) => {
toast.add({
mySwalToast({
title: err.message,
icon: "error",
timer: 2000,
});
this.resetCaptcha();
})
.finally(() => {

View File

@ -1,358 +0,0 @@
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,
// });
// },
},
};

View File

@ -1,5 +1,5 @@
import { mapState, mapActions } from "pinia";
import { useCommonStore } from "~/stores/commonStore";
import { useCommonStore } from "@stores/commonStore";
export default {
created() {

View File

@ -2,11 +2,6 @@
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 = "";
@ -18,19 +13,20 @@ 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 == "haditha") {
if (buildName == "hadith") {
const sourceDir = path.resolve(
__dirname,
`systems/${buildName.substring(
0,
buildName.length - 1
)}_ui/assets/${buildName}/images`
`systems/${buildName}_ui/assets/${buildName}/images`
); // Source folder (e.g., assets/images)
const targetDir = path.resolve(__dirname, `public/img/${buildName}`); // Target folder (e.g., public/images)
const targetDir = path.resolve(__dirname, "public/img"); // Target folder (e.g., public/images)
// Ensure the target directory exists
fs.ensureDirSync(targetDir);
@ -44,15 +40,96 @@ export default defineNuxtConfig({
"pages:extend"(pages) {
// Add custom routes
pages.push(...search, ...research, ...haditha, ...chat);
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 ---------------------
);
},
},
nitro: {
compressPublicAssets: true,
prerender: {
routes: ["/haditha/about-us", "/haditha/contact"], // Pre-render these routes
},
},
colorMode: {
@ -95,17 +172,6 @@ export default defineNuxtConfig({
"@nuxt/image",
// "@nuxtjs/supabase",
],
icon: {
customCollections: [
{
prefix: "haditha",
dir: `./systems/${buildName.substring(
0,
buildName.length - 1
)}_ui/assets/${buildName}/font-icons`,
},
],
},
// 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
@ -119,10 +185,29 @@ export default defineNuxtConfig({
// debug: process.env.NODE_ENV === 'development',
// mode: 'init'
// },
// image: {
// provider: "ipx",
// quality: 100,
// },
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,
},
},
},
},
i18n: {
vueI18n: "./i18n.config.ts", // if you are using custom path, default
},
@ -148,7 +233,7 @@ export default defineNuxtConfig({
},
},
css: [
customStyleLoader(),
mainStyle,
// "vue3-persian-datetime-picker/src/picker/assets/scss/style.scss",
],
alias: {
@ -168,8 +253,7 @@ export default defineNuxtConfig({
"@pages": "~/pages",
"@search": "~/systems/search_ui",
"@research": "~/systems/research_ui",
"@haditha": "~/systems/hadith_ui",
"@chat": "~/systems/chat_ui",
"@hadith": "~/systems/hadith_ui",
},
vite: {
resolve: {},
@ -191,10 +275,6 @@ export default defineNuxtConfig({
},
},
},
build: {
analyze: true,
// transpile: ["echarts", "resize-detector", "echarts-wordcloud"],
},
// postcss: {
// plugins: {
// tailwindcss: {},
@ -339,13 +419,3 @@ 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;
}

207
package-lock.json generated
View File

@ -17,8 +17,6 @@
"@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",
@ -31,8 +29,6 @@
"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",
@ -46,7 +42,6 @@
"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",
@ -58,12 +53,9 @@
"vue3-persian-datetime-picker": "^1.2.2",
"vue3-tree-vue": "^2.0.11",
"vuejs-paginate": "^2.1.0",
"vuejs-paginate-next": "^1.0.2",
"zod": "^3.24.2"
"vuejs-paginate-next": "^1.0.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",
@ -675,6 +667,7 @@
"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",
@ -719,6 +712,7 @@
"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",
@ -730,6 +724,7 @@
"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",
@ -753,126 +748,6 @@
"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",
@ -1588,26 +1463,6 @@
"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",
@ -6447,12 +6302,6 @@
"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",
@ -6996,6 +6845,7 @@
"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",
@ -7262,7 +7112,8 @@
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==",
"license": "MIT"
"license": "MIT",
"peer": true
},
"node_modules/croner": {
"version": "9.0.0",
@ -7282,16 +7133,6 @@
"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",
@ -11093,21 +10934,6 @@
"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",
@ -20584,16 +20410,6 @@
"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",
@ -21197,15 +21013,6 @@
"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",

View File

@ -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-haditha": "env-cmd -f .env.haditha nuxt dev --host --inspect",
"build-haditha": "env-cmd -f .env.haditha nuxt build"
"dev-hadith": "env-cmd -f .env.hadith nuxt dev --host --inspect",
"build-hadith": "env-cmd -f .env.hadith nuxt build"
},
"dependencies": {
"@nuxt/image": "^1.8.1",
@ -25,8 +25,6 @@
"@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",
@ -39,8 +37,6 @@
"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",
@ -54,7 +50,6 @@
"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",
@ -66,12 +61,9 @@
"vue3-persian-datetime-picker": "^1.2.2",
"vue3-tree-vue": "^2.0.11",
"vuejs-paginate": "^2.1.0",
"vuejs-paginate-next": "^1.0.2",
"zod": "^3.24.2"
"vuejs-paginate-next": "^1.0.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",

View File

@ -5,7 +5,7 @@
<!-- majles dashbaord -->
<search-section v-if="buildName() == 'majles'"></search-section>
<!-- monir dashboard -->
<default-dashboard v-else></default-dashboard>
<default-dashboard></default-dashboard>
<!-- </ClientOnly> -->
</NuxtLayout>
</div>

View File

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

View File

@ -3,13 +3,12 @@ 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 =
config.public.NUXT_PUBLIC_BASE_URL +
config.public.NUXT_PUBLIC_API_NAME +
import.meta.env.VITE_BASE_URL +
import.meta.env.VITE_API_NAME +
options.baseURL;
if (token) {
@ -41,14 +40,13 @@ export default defineNuxtPlugin((nuxtApp) => {
getRequest: (url, options = {}) => api(url, { method: "GET", ...options }),
postRequest: (url, body, options = {}) =>
api(url, { method: "POST", body, ...options }),
deleteRequest: (url, options = {}) =>
api(url, { method: "DELETE", ...options }),
deleteRequest: (url, options = {}) => api(url, { method: "DELETE", ...options }),
};
// Expose to useNuxtApp().$api and useNuxtApp().$http
return {
provide: {
http,
http
},
};
});

View File

@ -4,28 +4,23 @@
// 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((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.vueApp.use(() => {
// // Example of global setup, but typically you'd handle this in the component
// const state = reactive({
// firstName: ''
// })
// })
export default defineNuxtPlugin(nuxtApp => {
nuxtApp.provide('vuelidate', useVuelidate)
// const rules = {
// firstName: {
// required,
// minLength: minLength(2)
// }
// }
// const v$ = useVuelidate(rules, state)
// return v$;
// // Return the v$ instance or any other necessary setup
})
})

View File

Before

Width:  |  Height:  |  Size: 490 KiB

After

Width:  |  Height:  |  Size: 490 KiB

View File

Before

Width:  |  Height:  |  Size: 783 KiB

After

Width:  |  Height:  |  Size: 783 KiB

View File

Before

Width:  |  Height:  |  Size: 263 KiB

After

Width:  |  Height:  |  Size: 263 KiB

View File

Before

Width:  |  Height:  |  Size: 203 KiB

After

Width:  |  Height:  |  Size: 203 KiB

View File

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View File

Before

Width:  |  Height:  |  Size: 186 KiB

After

Width:  |  Height:  |  Size: 186 KiB

View File

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 113 KiB

View File

Before

Width:  |  Height:  |  Size: 198 KiB

After

Width:  |  Height:  |  Size: 198 KiB

View File

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

View File

Before

Width:  |  Height:  |  Size: 550 B

After

Width:  |  Height:  |  Size: 550 B

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,41 +0,0 @@
{
"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"
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -1,9 +0,0 @@
<svg width="16" height="27" viewBox="0 0 16 27" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.79031 13.8107C5.19508 12.8313 7.08122 10.8959 8 8.47239C8.91878 10.8959 10.8049 12.8313 13.2097 13.8107L13.5599 13.9533C10.9698 14.8404 8.92567 16.8559 8 19.427C7.07433 16.8559 5.03017 14.8404 2.44014 13.9533L2.79031 13.8107Z" stroke="url(#paint0_linear_67_6564)" stroke-linejoin="round"/>
<defs>
<linearGradient id="paint0_linear_67_6564" x1="15.0921" y1="7" x2="0.0931545" y2="7.27651" gradientUnits="userSpaceOnUse">
<stop stop-color="#D284FF"/>
<stop offset="1" stop-color="#4D00FF"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 630 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,59 +0,0 @@
<svg width="49" height="20" viewBox="0 0 49 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M27.3643 13.7278C28.4451 13.7278 29.2919 13.5665 29.9049 13.2439C30.534 12.9212 30.9857 12.4373 31.2599 11.7921L29.9049 4.02504L30.897 3.51691L32.2762 11.4775C32.3891 12.0905 32.6956 12.6228 33.1956 13.0745C33.7118 13.51 34.3813 13.7278 35.2039 13.7278H36.2202C36.3654 13.7278 36.4863 13.7923 36.5831 13.9214C36.696 14.0504 36.7525 14.2037 36.7525 14.3811C36.7525 14.5585 36.696 14.7118 36.5831 14.8408C36.4863 14.9699 36.3654 15.0344 36.2202 15.0344H35.4217C34.5022 15.0344 33.7279 14.8408 33.0988 14.4537C32.4697 14.0504 32.0342 13.51 31.7922 12.8325C31.4535 13.5262 30.9212 14.0665 30.1953 14.4537C29.4694 14.8408 28.558 15.0344 27.4611 15.0344H25.1261L25.0051 13.7278H27.3643Z" fill="url(#paint0_linear_67_1937)"/>
<path d="M36.1759 15.0344C36.0308 15.0344 35.9098 14.9699 35.813 14.8408C35.7001 14.7118 35.6436 14.5585 35.6436 14.3811C35.6436 14.1875 35.7001 14.0343 35.813 13.9214C35.9098 13.7923 36.0308 13.7278 36.1759 13.7278H45.8061L45.1286 8.74333C44.9673 7.66256 44.6044 6.85601 44.0398 6.32369C43.4913 5.77524 42.7735 5.50102 41.8863 5.50102C41.6927 5.50102 41.3862 5.53328 40.9668 5.5978L37.9907 6.08173L38.1117 4.77512L40.9426 4.31539C41.2814 4.267 41.604 4.2428 41.9105 4.2428C43.0719 4.2428 44.0317 4.59768 44.7899 5.30744C45.5641 6.00107 46.04 6.98506 46.2175 8.2594L46.9675 13.7278H49L48.6371 15.0344H36.1759Z" fill="url(#paint1_linear_67_1937)"/>
<path d="M18.8542 13.7277C19.8221 13.7277 20.6044 13.5503 21.2012 13.1954C21.8142 12.8405 22.2336 12.3324 22.4595 11.671L21.0803 4.70247L22.1691 4.21855L23.3547 10.0983C23.4192 10.4209 23.4515 10.7758 23.4515 11.1629C23.4515 12.3405 23.0482 13.2841 22.2417 13.9939C21.4513 14.6875 20.3382 15.0343 18.9026 15.0343C15.9956 15.0343 15.9065 13.7277 18.8542 13.7277Z" fill="url(#paint2_linear_67_1937)"/>
<path d="M12.9673 13.2438C13.5964 12.9212 14.0481 12.4373 14.3223 11.792L13.0811 5.96065L14.0732 5.45253L15.1983 10.3463L15.3386 11.4775C15.4515 12.0905 15.758 12.6228 16.258 13.0744C16.7742 13.51 17.4437 13.7277 18.2663 13.7277H19.2826C19.4278 13.7277 19.5487 13.7923 19.6455 13.9213C19.7584 14.0504 19.8149 14.2036 19.8149 14.381C19.8149 14.5585 19.7584 14.7117 19.6455 14.8408C19.5487 14.9698 19.4278 15.0343 19.2826 15.0343H18.4841C17.5646 15.0343 16.7903 14.8408 16.1612 14.4536C15.5321 14.0504 15.0966 13.51 14.8546 12.8325C14.5159 13.5261 13.9836 14.0665 13.2577 14.4536L12.9673 13.2438Z" fill="url(#paint3_linear_67_1937)"/>
<path d="M19.2383 15.0343C19.0932 15.0343 18.9722 14.9698 18.8754 14.8408C18.7625 14.7117 18.706 14.5585 18.706 14.381C18.706 14.1875 18.7625 14.0342 18.8754 13.9213C18.9722 13.7923 19.0932 13.7277 19.2383 13.7277V15.0343Z" fill="url(#paint4_linear_67_1937)"/>
<path d="M5.16444 15.0343C3.93849 15.0343 2.97064 14.6955 2.26087 14.018C1.55111 13.3405 1.19623 12.3646 1.19623 11.0903V2.63364L0 3.0117V1.65066L2.23668 0.927774V10.7031C2.23668 12.7195 3.2126 13.7277 5.16444 13.7277H5.72096C5.86614 13.7277 5.98712 13.7922 6.08391 13.9212C6.19682 14.0503 6.25328 14.2035 6.25328 14.381C6.25328 14.5584 6.19682 14.7117 6.08391 14.8407C5.98712 14.9697 5.86614 15.0343 5.72096 15.0343H5.16444Z" fill="url(#paint5_linear_67_1937)"/>
<path d="M5.68996 15.0343C5.54478 15.0343 5.4238 14.9697 5.32701 14.8407C5.2141 14.7117 5.15764 14.5584 5.15764 14.381C5.15764 14.2035 5.2141 14.0503 5.32701 13.9212C5.4238 13.7922 5.54478 13.7277 5.68996 13.7277H8.71451C8.85969 13.7277 8.98067 13.7922 9.07746 13.9212C9.19037 14.0503 9.24683 14.2035 9.24683 14.381C9.24683 14.5584 9.19037 14.7117 9.07746 14.8407C8.98067 14.9697 8.85969 15.0343 8.71451 15.0343H5.68996Z" fill="url(#paint6_linear_67_1937)"/>
<path d="M8.69031 15.0343C8.54513 15.0343 8.42415 14.9697 8.32737 14.8407C8.21445 14.7117 8.15799 14.5584 8.15799 14.381C8.15799 14.1874 8.21445 14.0342 8.32737 13.9212C8.42415 13.7922 8.54513 13.7277 8.69031 13.7277H10.6502C11.6181 13.7277 12.4004 13.5502 12.9973 13.1953C13.6102 12.8405 14.0297 12.3323 14.2555 11.671L12.9973 5.88501L14.0861 5.40108L15.1508 10.0982C15.2153 10.4208 15.2475 10.7757 15.2475 11.1628C15.2475 12.3404 14.8443 13.2841 14.0377 13.9938C13.2473 14.6875 12.1343 15.0343 10.6986 15.0343H8.69031Z" fill="url(#paint7_linear_67_1937)"/>
<path d="M7.02673 2.44065H12.0838V3.77145H7.02673V2.44065Z" fill="url(#paint8_linear_67_1937)"/>
<path d="M8.61989 0.253906H10.2834V1.61495H8.61989V0.253906Z" fill="url(#paint9_linear_67_1937)"/>
<path d="M17.3661 17.8477H22.3989V19.1785H17.3661V17.8477Z" fill="url(#paint10_linear_67_1937)"/>
<defs>
<linearGradient id="paint0_linear_67_1937" x1="4.93879" y1="12.9026" x2="-7.1352" y2="-9.309" gradientUnits="userSpaceOnUse">
<stop stop-color="#D284FF"/>
<stop offset="1" stop-color="#4D00FF"/>
</linearGradient>
<linearGradient id="paint1_linear_67_1937" x1="4.93879" y1="12.9026" x2="-7.1352" y2="-9.309" gradientUnits="userSpaceOnUse">
<stop stop-color="#D284FF"/>
<stop offset="1" stop-color="#4D00FF"/>
</linearGradient>
<linearGradient id="paint2_linear_67_1937" x1="4.93879" y1="12.9026" x2="-7.1352" y2="-9.309" gradientUnits="userSpaceOnUse">
<stop stop-color="#D284FF"/>
<stop offset="1" stop-color="#4D00FF"/>
</linearGradient>
<linearGradient id="paint3_linear_67_1937" x1="4.93879" y1="12.9026" x2="-7.1352" y2="-9.309" gradientUnits="userSpaceOnUse">
<stop stop-color="#D284FF"/>
<stop offset="1" stop-color="#4D00FF"/>
</linearGradient>
<linearGradient id="paint4_linear_67_1937" x1="4.93879" y1="12.9026" x2="-7.1352" y2="-9.309" gradientUnits="userSpaceOnUse">
<stop stop-color="#D284FF"/>
<stop offset="1" stop-color="#4D00FF"/>
</linearGradient>
<linearGradient id="paint5_linear_67_1937" x1="4.93879" y1="12.9026" x2="-7.1352" y2="-9.309" gradientUnits="userSpaceOnUse">
<stop stop-color="#D284FF"/>
<stop offset="1" stop-color="#4D00FF"/>
</linearGradient>
<linearGradient id="paint6_linear_67_1937" x1="4.93879" y1="12.9026" x2="-7.1352" y2="-9.309" gradientUnits="userSpaceOnUse">
<stop stop-color="#D284FF"/>
<stop offset="1" stop-color="#4D00FF"/>
</linearGradient>
<linearGradient id="paint7_linear_67_1937" x1="4.93879" y1="12.9026" x2="-7.1352" y2="-9.309" gradientUnits="userSpaceOnUse">
<stop stop-color="#D284FF"/>
<stop offset="1" stop-color="#4D00FF"/>
</linearGradient>
<linearGradient id="paint8_linear_67_1937" x1="4.93879" y1="12.9026" x2="-7.1352" y2="-9.309" gradientUnits="userSpaceOnUse">
<stop stop-color="#D284FF"/>
<stop offset="1" stop-color="#4D00FF"/>
</linearGradient>
<linearGradient id="paint9_linear_67_1937" x1="4.93879" y1="12.9026" x2="-7.1352" y2="-9.309" gradientUnits="userSpaceOnUse">
<stop stop-color="#D284FF"/>
<stop offset="1" stop-color="#4D00FF"/>
</linearGradient>
<linearGradient id="paint10_linear_67_1937" x1="4.93879" y1="12.9026" x2="-7.1352" y2="-9.309" gradientUnits="userSpaceOnUse">
<stop stop-color="#D284FF"/>
<stop offset="1" stop-color="#4D00FF"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 6.7 KiB

View File

Before

Width:  |  Height:  |  Size: 269 KiB

After

Width:  |  Height:  |  Size: 269 KiB

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

Before

Width:  |  Height:  |  Size: 304 KiB

After

Width:  |  Height:  |  Size: 304 KiB

View File

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 102 KiB

View File

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 95 KiB

View File

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 107 KiB

Some files were not shown because too many files have changed in this diff Show More