-
-
@@ -152,6 +166,8 @@ import {
Laptop,
BookOpenCheck,
Contact2,
+ Mail,
+ SendIcon,
} from 'lucide-vue-next'
import { formatTime } from '@/utils'
import CourseCard from '@/components/CourseCard.vue'
@@ -159,9 +175,12 @@ import BatchDashboard from '@/components/BatchDashboard.vue'
import LiveClass from '@/components/LiveClass.vue'
import BatchStudents from '@/components/BatchStudents.vue'
import Assessments from '@/components/Assessments.vue'
+import Announcements from '@/components/Annoucements.vue'
+import AnnouncementModal from '@/components/Modals/AnnouncementModal.vue'
const dayjs = inject('$dayjs')
const user = inject('$user')
+const showAnnouncementModal = ref(false)
const props = defineProps({
batchName: {
@@ -232,6 +251,11 @@ tabs.push({
icon: BookOpen,
})
+tabs.push({
+ label: 'Announcements',
+ icon: Mail,
+})
+
const courses = createResource({
url: 'lms.lms.utils.get_batch_courses',
params: {
@@ -244,4 +268,8 @@ const courses = createResource({
const redirectToLogin = () => {
window.location.href = `/login?redirect-to=/batches`
}
+
+const openAnnouncementModal = () => {
+ showAnnouncementModal.value = true
+}
diff --git a/frontend/src/utils/composables.js b/frontend/src/utils/composables.js
new file mode 100644
index 00000000..4ef97408
--- /dev/null
+++ b/frontend/src/utils/composables.js
@@ -0,0 +1,100 @@
+import { onMounted, onUnmounted, reactive, ref, watch } from 'vue'
+
+export function useScreenSize() {
+ const size = reactive({
+ width: window.innerWidth,
+ height: window.innerHeight,
+ })
+
+ const onResize = () => {
+ size.width = window.innerWidth
+ size.height = window.innerHeight
+ }
+
+ onMounted(() => {
+ window.addEventListener('resize', onResize)
+ })
+
+ onUnmounted(() => {
+ window.removeEventListener('resize', onResize)
+ })
+
+ return size
+}
+// write a composable for detecting swipe gestures in mobile devices
+export function useSwipe() {
+ const swipe = reactive({
+ initialX: null,
+ initialY: null,
+ currentX: null,
+ currentY: null,
+ diffX: null,
+ diffY: null,
+ absDiffX: null,
+ absDiffY: null,
+ direction: null,
+ })
+
+ const onTouchStart = (e) => {
+ swipe.initialX = e.touches[0].clientX
+ swipe.initialY = e.touches[0].clientY
+ swipe.direction = null
+ swipe.diffX = null
+ swipe.diffY = null
+ swipe.absDiffX = null
+ swipe.absDiffY = null
+ }
+
+ const onTouchMove = (e) => {
+ swipe.currentX = e.touches[0].clientX
+ swipe.currentY = e.touches[0].clientY
+
+ swipe.diffX = swipe.initialX - swipe.currentX
+ swipe.diffY = swipe.initialY - swipe.currentY
+
+ swipe.absDiffX = Math.abs(swipe.diffX)
+ swipe.absDiffY = Math.abs(swipe.diffY)
+ }
+
+ const onTouchEnd = (e) => {
+ let { diffX, diffY, absDiffX, absDiffY } = swipe
+ if (absDiffX > absDiffY) {
+ if (diffX > 0) {
+ swipe.direction = 'left'
+ } else {
+ swipe.direction = 'right'
+ }
+ } else {
+ if (diffY > 0) {
+ swipe.direction = 'up'
+ } else {
+ swipe.direction = 'down'
+ }
+ }
+ }
+
+ onMounted(() => {
+ window.addEventListener('touchstart', onTouchStart)
+ window.addEventListener('touchend', onTouchEnd)
+ window.addEventListener('touchmove', onTouchMove)
+ })
+
+ onUnmounted(() => {
+ window.removeEventListener('touchstart', onTouchStart)
+ window.removeEventListener('touchend', onTouchEnd)
+ window.removeEventListener('touchmove', onTouchMove)
+ })
+
+ return swipe
+}
+
+export function useLocalStorage(key, initialValue) {
+ let value = ref(null)
+ let storedValue = localStorage.getItem(key)
+ value.value = storedValue ? JSON.parse(storedValue) : initialValue
+
+ watch(value, (newValue) => {
+ localStorage.setItem(key, JSON.stringify(newValue))
+ })
+ return value
+}
diff --git a/frontend/src/utils/index.js b/frontend/src/utils/index.js
index 138cea80..4e5a812a 100644
--- a/frontend/src/utils/index.js
+++ b/frontend/src/utils/index.js
@@ -1,5 +1,6 @@
import { toast } from 'frappe-ui'
import { useDateFormat, useTimeAgo } from '@vueuse/core'
+import { BookOpen, Users, TrendingUp, Briefcase } from 'lucide-vue-next'
export function createToast(options) {
toast({
@@ -179,3 +180,28 @@ export function getTimezones() {
'Pacific/Apia',
]
}
+
+export function getSidebarLinks() {
+ return [
+ {
+ label: 'Courses',
+ icon: BookOpen,
+ to: 'Courses',
+ },
+ {
+ label: 'Batches',
+ icon: Users,
+ to: 'Batches',
+ },
+ {
+ label: 'Statistics',
+ icon: TrendingUp,
+ to: 'Statistics',
+ },
+ {
+ label: 'Jobs',
+ icon: Briefcase,
+ to: 'Jobs',
+ },
+ ]
+}