@burdenoff/microfe-buildmyiq 2026.509.101

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/README.md +12 -0
  2. package/dist/buildmyiq/BuildMyIQRoot.d.ts +5 -0
  3. package/dist/buildmyiq/BuildMyIQRoot.d.ts.map +1 -0
  4. package/dist/buildmyiq/BuildMyIQRoot.js +329 -0
  5. package/dist/buildmyiq/BuildMyIQRoot.js.map +1 -0
  6. package/dist/buildmyiq/BuildMyIQRoutes.d.ts +2 -0
  7. package/dist/buildmyiq/BuildMyIQRoutes.d.ts.map +1 -0
  8. package/dist/buildmyiq/BuildMyIQRoutes.js +171 -0
  9. package/dist/buildmyiq/BuildMyIQRoutes.js.map +1 -0
  10. package/dist/buildmyiq/index.d.ts +5 -0
  11. package/dist/buildmyiq/index.d.ts.map +1 -0
  12. package/dist/buildmyiq/index.js +3 -0
  13. package/dist/buildmyiq/pages/AdminAdminAnalyticsPagePage.d.ts +2 -0
  14. package/dist/buildmyiq/pages/AdminAdminAnalyticsPagePage.d.ts.map +1 -0
  15. package/dist/buildmyiq/pages/AdminAdminAnalyticsPagePage.js +271 -0
  16. package/dist/buildmyiq/pages/AdminAdminAnalyticsPagePage.js.map +1 -0
  17. package/dist/buildmyiq/pages/AdminAdminCoursesPagePage.d.ts +2 -0
  18. package/dist/buildmyiq/pages/AdminAdminCoursesPagePage.d.ts.map +1 -0
  19. package/dist/buildmyiq/pages/AdminAdminCoursesPagePage.js +212 -0
  20. package/dist/buildmyiq/pages/AdminAdminCoursesPagePage.js.map +1 -0
  21. package/dist/buildmyiq/pages/AdminAdminUsersPagePage.d.ts +2 -0
  22. package/dist/buildmyiq/pages/AdminAdminUsersPagePage.d.ts.map +1 -0
  23. package/dist/buildmyiq/pages/AdminAdminUsersPagePage.js +235 -0
  24. package/dist/buildmyiq/pages/AdminAdminUsersPagePage.js.map +1 -0
  25. package/dist/buildmyiq/pages/AdminIndexPage.d.ts +2 -0
  26. package/dist/buildmyiq/pages/AdminIndexPage.d.ts.map +1 -0
  27. package/dist/buildmyiq/pages/AdminIndexPage.js +274 -0
  28. package/dist/buildmyiq/pages/AdminIndexPage.js.map +1 -0
  29. package/dist/buildmyiq/pages/AiAichatPagePage.d.ts +2 -0
  30. package/dist/buildmyiq/pages/AiAichatPagePage.d.ts.map +1 -0
  31. package/dist/buildmyiq/pages/AiAichatPagePage.js +209 -0
  32. package/dist/buildmyiq/pages/AiAichatPagePage.js.map +1 -0
  33. package/dist/buildmyiq/pages/AiAicontentGenerationPagePage.d.ts +2 -0
  34. package/dist/buildmyiq/pages/AiAicontentGenerationPagePage.d.ts.map +1 -0
  35. package/dist/buildmyiq/pages/AiAicontentGenerationPagePage.js +318 -0
  36. package/dist/buildmyiq/pages/AiAicontentGenerationPagePage.js.map +1 -0
  37. package/dist/buildmyiq/pages/AiAitutoringPagePage.d.ts +2 -0
  38. package/dist/buildmyiq/pages/AiAitutoringPagePage.d.ts.map +1 -0
  39. package/dist/buildmyiq/pages/AiAitutoringPagePage.js +290 -0
  40. package/dist/buildmyiq/pages/AiAitutoringPagePage.js.map +1 -0
  41. package/dist/buildmyiq/pages/AiIndexPage.d.ts +2 -0
  42. package/dist/buildmyiq/pages/AiIndexPage.d.ts.map +1 -0
  43. package/dist/buildmyiq/pages/AiIndexPage.js +191 -0
  44. package/dist/buildmyiq/pages/AiIndexPage.js.map +1 -0
  45. package/dist/buildmyiq/pages/AssessmentsAssessmentBuilderPagePage.d.ts +2 -0
  46. package/dist/buildmyiq/pages/AssessmentsAssessmentBuilderPagePage.d.ts.map +1 -0
  47. package/dist/buildmyiq/pages/AssessmentsAssessmentBuilderPagePage.js +290 -0
  48. package/dist/buildmyiq/pages/AssessmentsAssessmentBuilderPagePage.js.map +1 -0
  49. package/dist/buildmyiq/pages/AssessmentsAssessmentGradingPagePage.d.ts +2 -0
  50. package/dist/buildmyiq/pages/AssessmentsAssessmentGradingPagePage.d.ts.map +1 -0
  51. package/dist/buildmyiq/pages/AssessmentsAssessmentGradingPagePage.js +215 -0
  52. package/dist/buildmyiq/pages/AssessmentsAssessmentGradingPagePage.js.map +1 -0
  53. package/dist/buildmyiq/pages/AssessmentsAssessmentResultsPagePage.d.ts +2 -0
  54. package/dist/buildmyiq/pages/AssessmentsAssessmentResultsPagePage.d.ts.map +1 -0
  55. package/dist/buildmyiq/pages/AssessmentsAssessmentResultsPagePage.js +224 -0
  56. package/dist/buildmyiq/pages/AssessmentsAssessmentResultsPagePage.js.map +1 -0
  57. package/dist/buildmyiq/pages/AssessmentsAssessmentTakePagePage.d.ts +2 -0
  58. package/dist/buildmyiq/pages/AssessmentsAssessmentTakePagePage.d.ts.map +1 -0
  59. package/dist/buildmyiq/pages/AssessmentsAssessmentTakePagePage.js +174 -0
  60. package/dist/buildmyiq/pages/AssessmentsAssessmentTakePagePage.js.map +1 -0
  61. package/dist/buildmyiq/pages/AssessmentsIndexPage.d.ts +2 -0
  62. package/dist/buildmyiq/pages/AssessmentsIndexPage.d.ts.map +1 -0
  63. package/dist/buildmyiq/pages/AssessmentsIndexPage.js +174 -0
  64. package/dist/buildmyiq/pages/AssessmentsIndexPage.js.map +1 -0
  65. package/dist/buildmyiq/pages/CalendarPage.d.ts +2 -0
  66. package/dist/buildmyiq/pages/CalendarPage.d.ts.map +1 -0
  67. package/dist/buildmyiq/pages/CalendarPage.js +242 -0
  68. package/dist/buildmyiq/pages/CalendarPage.js.map +1 -0
  69. package/dist/buildmyiq/pages/CommunicationAnnouncementsPagePage.d.ts +2 -0
  70. package/dist/buildmyiq/pages/CommunicationAnnouncementsPagePage.d.ts.map +1 -0
  71. package/dist/buildmyiq/pages/CommunicationAnnouncementsPagePage.js +180 -0
  72. package/dist/buildmyiq/pages/CommunicationAnnouncementsPagePage.js.map +1 -0
  73. package/dist/buildmyiq/pages/CommunicationForumsPagePage.d.ts +2 -0
  74. package/dist/buildmyiq/pages/CommunicationForumsPagePage.d.ts.map +1 -0
  75. package/dist/buildmyiq/pages/CommunicationForumsPagePage.js +154 -0
  76. package/dist/buildmyiq/pages/CommunicationForumsPagePage.js.map +1 -0
  77. package/dist/buildmyiq/pages/CommunicationIndexPage.d.ts +2 -0
  78. package/dist/buildmyiq/pages/CommunicationIndexPage.d.ts.map +1 -0
  79. package/dist/buildmyiq/pages/CommunicationIndexPage.js +191 -0
  80. package/dist/buildmyiq/pages/CommunicationIndexPage.js.map +1 -0
  81. package/dist/buildmyiq/pages/CommunicationMessagesPagePage.d.ts +2 -0
  82. package/dist/buildmyiq/pages/CommunicationMessagesPagePage.d.ts.map +1 -0
  83. package/dist/buildmyiq/pages/CommunicationMessagesPagePage.js +261 -0
  84. package/dist/buildmyiq/pages/CommunicationMessagesPagePage.js.map +1 -0
  85. package/dist/buildmyiq/pages/CoursesCourseContentPagePage.d.ts +2 -0
  86. package/dist/buildmyiq/pages/CoursesCourseContentPagePage.d.ts.map +1 -0
  87. package/dist/buildmyiq/pages/CoursesCourseContentPagePage.js +164 -0
  88. package/dist/buildmyiq/pages/CoursesCourseContentPagePage.js.map +1 -0
  89. package/dist/buildmyiq/pages/CoursesCourseCreatePagePage.d.ts +2 -0
  90. package/dist/buildmyiq/pages/CoursesCourseCreatePagePage.d.ts.map +1 -0
  91. package/dist/buildmyiq/pages/CoursesCourseCreatePagePage.js +239 -0
  92. package/dist/buildmyiq/pages/CoursesCourseCreatePagePage.js.map +1 -0
  93. package/dist/buildmyiq/pages/CoursesCourseDashboardPagePage.d.ts +2 -0
  94. package/dist/buildmyiq/pages/CoursesCourseDashboardPagePage.d.ts.map +1 -0
  95. package/dist/buildmyiq/pages/CoursesCourseDashboardPagePage.js +368 -0
  96. package/dist/buildmyiq/pages/CoursesCourseDashboardPagePage.js.map +1 -0
  97. package/dist/buildmyiq/pages/CoursesCourseDetailPagePage.d.ts +2 -0
  98. package/dist/buildmyiq/pages/CoursesCourseDetailPagePage.d.ts.map +1 -0
  99. package/dist/buildmyiq/pages/CoursesCourseDetailPagePage.js +219 -0
  100. package/dist/buildmyiq/pages/CoursesCourseDetailPagePage.js.map +1 -0
  101. package/dist/buildmyiq/pages/CoursesCourseListPagePage.d.ts +2 -0
  102. package/dist/buildmyiq/pages/CoursesCourseListPagePage.d.ts.map +1 -0
  103. package/dist/buildmyiq/pages/CoursesCourseListPagePage.js +153 -0
  104. package/dist/buildmyiq/pages/CoursesCourseListPagePage.js.map +1 -0
  105. package/dist/buildmyiq/pages/CoursesIndexPage.d.ts +2 -0
  106. package/dist/buildmyiq/pages/CoursesIndexPage.d.ts.map +1 -0
  107. package/dist/buildmyiq/pages/CoursesIndexPage.js +138 -0
  108. package/dist/buildmyiq/pages/CoursesIndexPage.js.map +1 -0
  109. package/dist/buildmyiq/pages/DashboardPage.d.ts +2 -0
  110. package/dist/buildmyiq/pages/DashboardPage.d.ts.map +1 -0
  111. package/dist/buildmyiq/pages/DashboardPage.js +264 -0
  112. package/dist/buildmyiq/pages/DashboardPage.js.map +1 -0
  113. package/dist/buildmyiq/pages/MessagesPage.d.ts +2 -0
  114. package/dist/buildmyiq/pages/MessagesPage.d.ts.map +1 -0
  115. package/dist/buildmyiq/pages/MessagesPage.js +261 -0
  116. package/dist/buildmyiq/pages/MessagesPage.js.map +1 -0
  117. package/dist/buildmyiq/pages/ProfileProgressPage.d.ts +2 -0
  118. package/dist/buildmyiq/pages/ProfileProgressPage.d.ts.map +1 -0
  119. package/dist/buildmyiq/pages/ProfileProgressPage.js +194 -0
  120. package/dist/buildmyiq/pages/ProfileProgressPage.js.map +1 -0
  121. package/dist/buildmyiq/pages/TeachingAnalyticsPage.d.ts +2 -0
  122. package/dist/buildmyiq/pages/TeachingAnalyticsPage.d.ts.map +1 -0
  123. package/dist/buildmyiq/pages/TeachingAnalyticsPage.js +243 -0
  124. package/dist/buildmyiq/pages/TeachingAnalyticsPage.js.map +1 -0
  125. package/dist/buildmyiq/pages/TeachingContentPage.d.ts +2 -0
  126. package/dist/buildmyiq/pages/TeachingContentPage.d.ts.map +1 -0
  127. package/dist/buildmyiq/pages/TeachingContentPage.js +165 -0
  128. package/dist/buildmyiq/pages/TeachingContentPage.js.map +1 -0
  129. package/dist/buildmyiq/pages/TeachingCoursesPage.d.ts +2 -0
  130. package/dist/buildmyiq/pages/TeachingCoursesPage.d.ts.map +1 -0
  131. package/dist/buildmyiq/pages/TeachingCoursesPage.js +151 -0
  132. package/dist/buildmyiq/pages/TeachingCoursesPage.js.map +1 -0
  133. package/dist/buildmyiq/pages/TeachingGradingPage.d.ts +2 -0
  134. package/dist/buildmyiq/pages/TeachingGradingPage.d.ts.map +1 -0
  135. package/dist/buildmyiq/pages/TeachingGradingPage.js +204 -0
  136. package/dist/buildmyiq/pages/TeachingGradingPage.js.map +1 -0
  137. package/dist/buildmyiq/pages/TeachingIndexPage.d.ts +2 -0
  138. package/dist/buildmyiq/pages/TeachingIndexPage.d.ts.map +1 -0
  139. package/dist/buildmyiq/pages/TeachingIndexPage.js +220 -0
  140. package/dist/buildmyiq/pages/TeachingIndexPage.js.map +1 -0
  141. package/dist/buildmyiq/pages/TeachingLessonPlansPage.d.ts +2 -0
  142. package/dist/buildmyiq/pages/TeachingLessonPlansPage.d.ts.map +1 -0
  143. package/dist/buildmyiq/pages/TeachingLessonPlansPage.js +157 -0
  144. package/dist/buildmyiq/pages/TeachingLessonPlansPage.js.map +1 -0
  145. package/dist/buildmyiq/pages/TeachingQuestionsPage.d.ts +2 -0
  146. package/dist/buildmyiq/pages/TeachingQuestionsPage.d.ts.map +1 -0
  147. package/dist/buildmyiq/pages/TeachingQuestionsPage.js +184 -0
  148. package/dist/buildmyiq/pages/TeachingQuestionsPage.js.map +1 -0
  149. package/dist/buildmyiq/pages/TeachingStudentsPage.d.ts +2 -0
  150. package/dist/buildmyiq/pages/TeachingStudentsPage.d.ts.map +1 -0
  151. package/dist/buildmyiq/pages/TeachingStudentsPage.js +204 -0
  152. package/dist/buildmyiq/pages/TeachingStudentsPage.js.map +1 -0
  153. package/dist/buildmyiq/providers/BuildMyIQProvider.d.ts +6 -0
  154. package/dist/buildmyiq/providers/BuildMyIQProvider.d.ts.map +1 -0
  155. package/dist/buildmyiq/providers/BuildMyIQProvider.js +27 -0
  156. package/dist/buildmyiq/providers/BuildMyIQProvider.js.map +1 -0
  157. package/dist/buildmyiq/store/buildmyiqStore.d.ts +189 -0
  158. package/dist/buildmyiq/store/buildmyiqStore.d.ts.map +1 -0
  159. package/dist/buildmyiq/store/buildmyiqStore.js +1160 -0
  160. package/dist/buildmyiq/store/buildmyiqStore.js.map +1 -0
  161. package/dist/buildmyiq/types/index.d.ts +51 -0
  162. package/dist/buildmyiq/types/index.d.ts.map +1 -0
  163. package/dist/buildmyiq/utils/cn.d.ts +4 -0
  164. package/dist/buildmyiq/utils/cn.d.ts.map +1 -0
  165. package/dist/buildmyiq/utils/navigation.d.ts +2 -0
  166. package/dist/buildmyiq/utils/navigation.d.ts.map +1 -0
  167. package/dist/buildmyiq/utils/navigation.js +8 -0
  168. package/dist/buildmyiq/utils/navigation.js.map +1 -0
  169. package/dist/dev/main.d.ts +2 -0
  170. package/dist/dev/main.d.ts.map +1 -0
  171. package/dist/generated/global-operations.d.ts +2 -0
  172. package/dist/generated/global-operations.d.ts.map +1 -0
  173. package/dist/generated/global-types.d.ts +18199 -0
  174. package/dist/generated/global-types.d.ts.map +1 -0
  175. package/dist/generated/wspace-operations.d.ts +2 -0
  176. package/dist/generated/wspace-operations.d.ts.map +1 -0
  177. package/dist/generated/wspace-types.d.ts +43046 -0
  178. package/dist/generated/wspace-types.d.ts.map +1 -0
  179. package/dist/index.d.ts +2 -0
  180. package/dist/index.d.ts.map +1 -0
  181. package/dist/index.js +5 -0
  182. package/package.json +107 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssessmentsIndexPage.js","names":[],"sources":["../../../src/buildmyiq/pages/AssessmentsIndexPage.tsx"],"sourcesContent":["import {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n Badge,\n Button,\n Input,\n} from '@burdenoff/fe-libs/ui';\nimport {\n FileText,\n Plus,\n Search,\n Filter,\n Clock,\n Users,\n BarChart3,\n Calendar,\n CheckCircle,\n PenTool,\n Eye,\n Edit,\n Play,\n AlertCircle,\n} from 'lucide-react';\nimport { useState } from 'react';\nimport { useBuildMyIQStore } from '../store/buildmyiqStore';\n\nexport function AssessmentsIndexPage() {\n const { assessments } = useBuildMyIQStore();\n const [searchTerm, setSearchTerm] = useState('');\n\n const filtered = assessments.filter(\n (a) => searchTerm === '' || a.title.toLowerCase().includes(searchTerm.toLowerCase())\n );\n const stats = [\n { title: 'Total Assessments', value: String(assessments.length), icon: FileText },\n {\n title: 'Pending Grading',\n value: String(assessments.filter((a) => a.status === 'grading').length),\n icon: Clock,\n },\n {\n title: 'Avg Score',\n value: `${Math.round(assessments.filter((a) => a.averageScore !== null).reduce((s, a) => s + (a.averageScore ?? 0), 0) / assessments.filter((a) => a.averageScore !== null).length)}%`,\n icon: BarChart3,\n },\n ];\n\n const getTypeIcon = (type: string) =>\n type === 'exam' ? FileText : type === 'quiz' ? CheckCircle : PenTool;\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Assessments</h1>\n <p className=\"text-sm text-muted-foreground\">\n Create and manage assessments for your courses\n </p>\n </div>\n <Button size=\"sm\">\n <Plus className=\"mr-2 h-4 w-4\" />\n Create Assessment\n </Button>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-3\">\n {stats.map((stat) => (\n <Card key={stat.title}>\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">{stat.title}</CardTitle>\n <stat.icon className=\"h-4 w-4 text-muted-foreground\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold\">{stat.value}</div>\n </CardContent>\n </Card>\n ))}\n </div>\n\n <div className=\"flex gap-4\">\n <div className=\"relative flex-1 max-w-md\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\n <Input\n placeholder=\"Search assessments...\"\n value={searchTerm}\n onChange={(e) => setSearchTerm(e.target.value)}\n className=\"pl-10\"\n />\n </div>\n <Button variant=\"outline\" size=\"sm\">\n <Filter className=\"mr-2 h-4 w-4\" />\n Filter\n </Button>\n <Button variant=\"outline\" size=\"sm\">\n <Calendar className=\"mr-2 h-4 w-4\" />\n Due Date\n </Button>\n </div>\n\n <div className=\"space-y-4\">\n {filtered.map((assessment) => {\n const TypeIcon = getTypeIcon(assessment.type);\n return (\n <Card key={assessment.id}>\n <CardContent className=\"pt-6\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-4 flex-1\">\n <div className=\"p-3 bg-primary/10 rounded-lg\">\n <TypeIcon className=\"h-6 w-6 text-primary\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 mb-1\">\n <h3 className=\"font-semibold truncate\">{assessment.title}</h3>\n <Badge\n variant={\n assessment.status === 'published'\n ? 'default'\n : assessment.status === 'draft'\n ? 'secondary'\n : 'destructive'\n }\n >\n {assessment.status}\n </Badge>\n </div>\n <p className=\"text-sm text-muted-foreground mb-2\">{assessment.course}</p>\n <div className=\"flex items-center gap-4 text-xs text-muted-foreground\">\n <span className=\"flex items-center gap-1\">\n <FileText className=\"h-3 w-3\" />\n {assessment.questions} questions\n </span>\n {assessment.duration && (\n <span className=\"flex items-center gap-1\">\n <Clock className=\"h-3 w-3\" />\n {assessment.duration} min\n </span>\n )}\n <span className=\"flex items-center gap-1\">\n <Calendar className=\"h-3 w-3\" />\n Due {assessment.dueDate}\n </span>\n <span className=\"flex items-center gap-1\">\n <Users className=\"h-3 w-3\" />\n {assessment.submissions}/{assessment.totalStudents}\n </span>\n </div>\n </div>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" size=\"sm\">\n <Eye className=\"mr-2 h-4 w-4\" />\n Results\n </Button>\n <Button variant=\"outline\" size=\"sm\">\n <Edit className=\"mr-2 h-4 w-4\" />\n Edit\n </Button>\n {assessment.submissions > 0 && (\n <Button size=\"sm\">\n <CheckCircle className=\"mr-2 h-4 w-4\" />\n Grade\n </Button>\n )}\n </div>\n </div>\n </CardContent>\n </Card>\n );\n })}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function CalendarPage(): import("react/jsx-runtime").JSX.Element;
2
+ //# sourceMappingURL=CalendarPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CalendarPage.d.ts","sourceRoot":"","sources":["../../../src/buildmyiq/pages/CalendarPage.tsx"],"names":[],"mappings":"AAmBA,wBAAgB,YAAY,4CAqP3B"}
@@ -0,0 +1,242 @@
1
+ import { useBuildMyIQStore as e } from "../store/buildmyiqStore.js";
2
+ import { useState as t } from "react";
3
+ import { AlertCircle as n, BookOpen as r, Calendar as i, Clock as a, Filter as o, FlaskConical as s, GraduationCap as c, MapPin as l, Plus as u, Users as d } from "lucide-react";
4
+ import { jsx as f, jsxs as p } from "react/jsx-runtime";
5
+ import { Badge as m, Button as h, Card as g, CardContent as _, CardHeader as v, CardTitle as y } from "@burdenoff/fe-libs/ui";
6
+ import { useI18n as b } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
7
+ //#region src/buildmyiq/pages/CalendarPage.tsx
8
+ function x() {
9
+ let { t: x } = b(), S = (e, t) => {
10
+ let n = x(e);
11
+ return n === e ? t : n;
12
+ }, { calendarEvents: C } = e(), [w, T] = t("all"), [E, D] = t("all"), O = {
13
+ lecture: {
14
+ label: S("buildmyiq.calendar.eventTypes.lecture", "Lecture"),
15
+ color: "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400",
16
+ icon: r
17
+ },
18
+ exam: {
19
+ label: S("buildmyiq.calendar.eventTypes.exam", "Exam"),
20
+ color: "bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-400",
21
+ icon: c
22
+ },
23
+ assignment: {
24
+ label: S("buildmyiq.calendar.eventTypes.assignment", "Assignment"),
25
+ color: "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400",
26
+ icon: n
27
+ },
28
+ lab: {
29
+ label: S("buildmyiq.calendar.eventTypes.lab", "Lab"),
30
+ color: "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400",
31
+ icon: s
32
+ },
33
+ office_hours: {
34
+ label: S("buildmyiq.calendar.eventTypes.officeHours", "Office Hours"),
35
+ color: "bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400",
36
+ icon: d
37
+ }
38
+ }, k = ["all", ...Array.from(new Set(C.map((e) => e.course)))], A = C.filter((e) => {
39
+ let t = w === "all" || e.type === w, n = E === "all" || e.course === E;
40
+ return t && n;
41
+ }), j = A.reduce((e, t) => (e[t.date] || (e[t.date] = []), e[t.date].push(t), e), {}), M = Object.keys(j).sort((e, t) => new Date(e).getTime() - new Date(t).getTime());
42
+ return /* @__PURE__ */ p("div", {
43
+ className: "space-y-6 p-6",
44
+ children: [/* @__PURE__ */ p("div", {
45
+ className: "flex items-center justify-between",
46
+ children: [/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("h1", {
47
+ className: "text-2xl font-semibold",
48
+ children: S("buildmyiq.calendar.title", "Calendar")
49
+ }), /* @__PURE__ */ f("p", {
50
+ className: "text-sm text-muted-foreground",
51
+ children: S("buildmyiq.calendar.subtitle", "View and manage your schedule, events, and deadlines")
52
+ })] }), /* @__PURE__ */ p(h, {
53
+ size: "sm",
54
+ children: [/* @__PURE__ */ f(u, { className: "mr-2 h-4 w-4" }), S("buildmyiq.calendar.actions.addEvent", "Add Event")]
55
+ })]
56
+ }), /* @__PURE__ */ p("div", {
57
+ className: "grid grid-cols-1 lg:grid-cols-12 gap-6",
58
+ children: [/* @__PURE__ */ p("div", {
59
+ className: "lg:col-span-3 space-y-4",
60
+ children: [
61
+ /* @__PURE__ */ p(g, { children: [/* @__PURE__ */ f(v, {
62
+ className: "pb-2",
63
+ children: /* @__PURE__ */ f(y, {
64
+ className: "text-sm",
65
+ children: S("buildmyiq.calendar.filters.eventType", "Event Type")
66
+ })
67
+ }), /* @__PURE__ */ p(_, {
68
+ className: "space-y-1",
69
+ children: [/* @__PURE__ */ p("button", {
70
+ onClick: () => T("all"),
71
+ className: `w-full flex items-center gap-2 rounded-md px-3 py-2 text-sm ${w === "all" ? "bg-primary text-primary-foreground" : "hover:bg-muted"}`,
72
+ children: [
73
+ /* @__PURE__ */ f(o, { className: "h-4 w-4" }),
74
+ /* @__PURE__ */ f("span", { children: S("buildmyiq.calendar.filters.allEvents", "All Events") }),
75
+ /* @__PURE__ */ f("span", {
76
+ className: "ml-auto font-bold",
77
+ children: C.length
78
+ })
79
+ ]
80
+ }), Object.keys(O).map((e) => {
81
+ let t = O[e], n = C.filter((t) => t.type === e).length;
82
+ return /* @__PURE__ */ p("button", {
83
+ onClick: () => T(e),
84
+ className: `w-full flex items-center gap-2 rounded-md px-3 py-2 text-sm ${w === e ? "bg-primary text-primary-foreground" : "hover:bg-muted"}`,
85
+ children: [
86
+ /* @__PURE__ */ f(t.icon, { className: "h-4 w-4" }),
87
+ /* @__PURE__ */ f("span", { children: t.label }),
88
+ /* @__PURE__ */ f("span", {
89
+ className: "ml-auto font-bold",
90
+ children: n
91
+ })
92
+ ]
93
+ }, e);
94
+ })]
95
+ })] }),
96
+ /* @__PURE__ */ p(g, { children: [/* @__PURE__ */ f(v, {
97
+ className: "pb-2",
98
+ children: /* @__PURE__ */ f(y, {
99
+ className: "text-sm",
100
+ children: S("buildmyiq.calendar.filters.course", "Filter by Course")
101
+ })
102
+ }), /* @__PURE__ */ f(_, {
103
+ className: "space-y-1",
104
+ children: k.map((e) => /* @__PURE__ */ f("button", {
105
+ onClick: () => D(e),
106
+ className: `w-full text-left rounded-md px-3 py-2 text-sm ${E === e ? "bg-primary text-primary-foreground" : "hover:bg-muted"}`,
107
+ children: e === "all" ? S("buildmyiq.calendar.filters.allCourses", "All Courses") : e
108
+ }, e))
109
+ })] }),
110
+ /* @__PURE__ */ p(g, { children: [/* @__PURE__ */ f(v, {
111
+ className: "pb-2",
112
+ children: /* @__PURE__ */ f(y, {
113
+ className: "text-sm",
114
+ children: S("buildmyiq.calendar.thisWeek.title", "This Week")
115
+ })
116
+ }), /* @__PURE__ */ p(_, {
117
+ className: "space-y-2",
118
+ children: [
119
+ /* @__PURE__ */ p("div", {
120
+ className: "flex justify-between",
121
+ children: [/* @__PURE__ */ f("span", {
122
+ className: "text-sm text-muted-foreground",
123
+ children: S("buildmyiq.calendar.thisWeek.total", "Total")
124
+ }), /* @__PURE__ */ f("span", {
125
+ className: "font-bold",
126
+ children: A.length
127
+ })]
128
+ }),
129
+ /* @__PURE__ */ p("div", {
130
+ className: "flex justify-between",
131
+ children: [/* @__PURE__ */ f("span", {
132
+ className: "text-sm text-muted-foreground",
133
+ children: S("buildmyiq.calendar.thisWeek.lectures", "Lectures")
134
+ }), /* @__PURE__ */ f("span", {
135
+ className: "font-bold text-blue-600",
136
+ children: A.filter((e) => e.type === "lecture").length
137
+ })]
138
+ }),
139
+ /* @__PURE__ */ p("div", {
140
+ className: "flex justify-between",
141
+ children: [/* @__PURE__ */ f("span", {
142
+ className: "text-sm text-muted-foreground",
143
+ children: S("buildmyiq.calendar.thisWeek.exams", "Exams")
144
+ }), /* @__PURE__ */ f("span", {
145
+ className: "font-bold text-orange-600",
146
+ children: A.filter((e) => e.type === "exam").length
147
+ })]
148
+ }),
149
+ /* @__PURE__ */ p("div", {
150
+ className: "flex justify-between",
151
+ children: [/* @__PURE__ */ f("span", {
152
+ className: "text-sm text-muted-foreground",
153
+ children: S("buildmyiq.calendar.thisWeek.deadlines", "Deadlines")
154
+ }), /* @__PURE__ */ f("span", {
155
+ className: "font-bold text-red-600",
156
+ children: A.filter((e) => e.type === "assignment").length
157
+ })]
158
+ })
159
+ ]
160
+ })] })
161
+ ]
162
+ }), /* @__PURE__ */ f("div", {
163
+ className: "lg:col-span-9 space-y-6",
164
+ children: M.length === 0 ? /* @__PURE__ */ f(g, { children: /* @__PURE__ */ p(_, {
165
+ className: "py-16 text-center",
166
+ children: [/* @__PURE__ */ f(i, { className: "h-12 w-12 mx-auto mb-3 text-muted-foreground" }), /* @__PURE__ */ f("p", {
167
+ className: "text-muted-foreground",
168
+ children: S("buildmyiq.calendar.emptyState", "No events found. Try adjusting your filters.")
169
+ })]
170
+ }) }) : M.map((e) => /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ p("div", {
171
+ className: "flex items-center gap-2 mb-3",
172
+ children: [/* @__PURE__ */ f("h2", {
173
+ className: "text-lg font-semibold",
174
+ children: new Date(e).toLocaleDateString("en-US", {
175
+ weekday: "long",
176
+ month: "long",
177
+ day: "numeric",
178
+ year: "numeric"
179
+ })
180
+ }), /* @__PURE__ */ p(m, {
181
+ variant: "secondary",
182
+ children: [
183
+ j[e].length,
184
+ " ",
185
+ j[e].length === 1 ? S("buildmyiq.calendar.eventCount.singular", "event") : S("buildmyiq.calendar.eventCount.plural", "events")
186
+ ]
187
+ })]
188
+ }), /* @__PURE__ */ f("div", {
189
+ className: "space-y-3",
190
+ children: j[e].map((e) => {
191
+ let t = O[e.type];
192
+ return /* @__PURE__ */ f(g, {
193
+ className: "hover:shadow-md transition-shadow",
194
+ children: /* @__PURE__ */ f(_, {
195
+ className: "py-4",
196
+ children: /* @__PURE__ */ p("div", {
197
+ className: "flex items-start gap-4",
198
+ children: [/* @__PURE__ */ f("div", {
199
+ className: `rounded-lg p-2 ${t.color.split(" ").slice(0, 1).join(" ")}`,
200
+ children: /* @__PURE__ */ f(t.icon, { className: `h-5 w-5 ${t.color.split(" ").slice(1).join(" ")}` })
201
+ }), /* @__PURE__ */ p("div", {
202
+ className: "flex-1",
203
+ children: [
204
+ /* @__PURE__ */ p("div", {
205
+ className: "flex items-center gap-2 mb-1",
206
+ children: [/* @__PURE__ */ f("h3", {
207
+ className: "font-medium",
208
+ children: e.title
209
+ }), /* @__PURE__ */ f(m, {
210
+ className: t.color,
211
+ children: t.label
212
+ })]
213
+ }),
214
+ /* @__PURE__ */ f("p", {
215
+ className: "text-sm text-muted-foreground mb-2",
216
+ children: e.course
217
+ }),
218
+ /* @__PURE__ */ p("div", {
219
+ className: "flex items-center gap-4 text-sm text-muted-foreground",
220
+ children: [/* @__PURE__ */ p("div", {
221
+ className: "flex items-center gap-1",
222
+ children: [/* @__PURE__ */ f(a, { className: "h-4 w-4" }), e.time]
223
+ }), /* @__PURE__ */ p("div", {
224
+ className: "flex items-center gap-1",
225
+ children: [/* @__PURE__ */ f(l, { className: "h-4 w-4" }), e.location]
226
+ })]
227
+ })
228
+ ]
229
+ })]
230
+ })
231
+ })
232
+ }, e.id);
233
+ })
234
+ })] }, e))
235
+ })]
236
+ })]
237
+ });
238
+ }
239
+ //#endregion
240
+ export { x as CalendarPage };
241
+
242
+ //# sourceMappingURL=CalendarPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CalendarPage.js","names":[],"sources":["../../../src/buildmyiq/pages/CalendarPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { Badge, Button, Card, CardContent, CardHeader, CardTitle } from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n Calendar as CalendarIcon,\n Clock,\n MapPin,\n Plus,\n BookOpen,\n GraduationCap,\n FlaskConical,\n Users,\n AlertCircle,\n Filter,\n} from 'lucide-react';\nimport { useBuildMyIQStore } from '../store/buildmyiqStore';\n\ntype EventType = 'all' | 'lecture' | 'exam' | 'assignment' | 'lab' | 'office_hours';\n\nexport function CalendarPage() {\n const { t: translate } = useI18n();\n const t = (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n };\n const { calendarEvents } = useBuildMyIQStore();\n const [typeFilter, setTypeFilter] = useState<EventType>('all');\n const [courseFilter, setCourseFilter] = useState('all');\n\n const typeConfig: Record<string, { label: string; color: string; icon: typeof BookOpen }> = {\n lecture: {\n label: t('buildmyiq.calendar.eventTypes.lecture', 'Lecture'),\n color: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400',\n icon: BookOpen,\n },\n exam: {\n label: t('buildmyiq.calendar.eventTypes.exam', 'Exam'),\n color: 'bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-400',\n icon: GraduationCap,\n },\n assignment: {\n label: t('buildmyiq.calendar.eventTypes.assignment', 'Assignment'),\n color: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400',\n icon: AlertCircle,\n },\n lab: {\n label: t('buildmyiq.calendar.eventTypes.lab', 'Lab'),\n color: 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400',\n icon: FlaskConical,\n },\n office_hours: {\n label: t('buildmyiq.calendar.eventTypes.officeHours', 'Office Hours'),\n color: 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400',\n icon: Users,\n },\n };\n\n const courses = ['all', ...Array.from(new Set(calendarEvents.map((e) => e.course)))];\n\n const filtered = calendarEvents.filter((e) => {\n const matchesType = typeFilter === 'all' || e.type === typeFilter;\n const matchesCourse = courseFilter === 'all' || e.course === courseFilter;\n return matchesType && matchesCourse;\n });\n\n const eventsByDate = filtered.reduce<Record<string, typeof filtered>>((acc, evt) => {\n if (!acc[evt.date]) acc[evt.date] = [];\n acc[evt.date].push(evt);\n return acc;\n }, {});\n\n const sortedDates = Object.keys(eventsByDate).sort(\n (a, b) => new Date(a).getTime() - new Date(b).getTime()\n );\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">{t('buildmyiq.calendar.title', 'Calendar')}</h1>\n <p className=\"text-sm text-muted-foreground\">\n {t(\n 'buildmyiq.calendar.subtitle',\n 'View and manage your schedule, events, and deadlines'\n )}\n </p>\n </div>\n <Button size=\"sm\">\n <Plus className=\"mr-2 h-4 w-4\" />\n {t('buildmyiq.calendar.actions.addEvent', 'Add Event')}\n </Button>\n </div>\n\n <div className=\"grid grid-cols-1 lg:grid-cols-12 gap-6\">\n <div className=\"lg:col-span-3 space-y-4\">\n <Card>\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"text-sm\">\n {t('buildmyiq.calendar.filters.eventType', 'Event Type')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-1\">\n <button\n onClick={() => setTypeFilter('all')}\n className={`w-full flex items-center gap-2 rounded-md px-3 py-2 text-sm ${typeFilter === 'all' ? 'bg-primary text-primary-foreground' : 'hover:bg-muted'}`}\n >\n <Filter className=\"h-4 w-4\" />\n <span>{t('buildmyiq.calendar.filters.allEvents', 'All Events')}</span>\n <span className=\"ml-auto font-bold\">{calendarEvents.length}</span>\n </button>\n {(Object.keys(typeConfig) as EventType[]).map((t) => {\n const cfg = typeConfig[t];\n const count = calendarEvents.filter((e) => e.type === t).length;\n return (\n <button\n key={t}\n onClick={() => setTypeFilter(t)}\n className={`w-full flex items-center gap-2 rounded-md px-3 py-2 text-sm ${typeFilter === t ? 'bg-primary text-primary-foreground' : 'hover:bg-muted'}`}\n >\n <cfg.icon className=\"h-4 w-4\" />\n <span>{cfg.label}</span>\n <span className=\"ml-auto font-bold\">{count}</span>\n </button>\n );\n })}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"text-sm\">\n {t('buildmyiq.calendar.filters.course', 'Filter by Course')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-1\">\n {courses.map((c) => (\n <button\n key={c}\n onClick={() => setCourseFilter(c)}\n className={`w-full text-left rounded-md px-3 py-2 text-sm ${courseFilter === c ? 'bg-primary text-primary-foreground' : 'hover:bg-muted'}`}\n >\n {c === 'all' ? t('buildmyiq.calendar.filters.allCourses', 'All Courses') : c}\n </button>\n ))}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"text-sm\">\n {t('buildmyiq.calendar.thisWeek.title', 'This Week')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n <div className=\"flex justify-between\">\n <span className=\"text-sm text-muted-foreground\">\n {t('buildmyiq.calendar.thisWeek.total', 'Total')}\n </span>\n <span className=\"font-bold\">{filtered.length}</span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-sm text-muted-foreground\">\n {t('buildmyiq.calendar.thisWeek.lectures', 'Lectures')}\n </span>\n <span className=\"font-bold text-blue-600\">\n {filtered.filter((e) => e.type === 'lecture').length}\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-sm text-muted-foreground\">\n {t('buildmyiq.calendar.thisWeek.exams', 'Exams')}\n </span>\n <span className=\"font-bold text-orange-600\">\n {filtered.filter((e) => e.type === 'exam').length}\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-sm text-muted-foreground\">\n {t('buildmyiq.calendar.thisWeek.deadlines', 'Deadlines')}\n </span>\n <span className=\"font-bold text-red-600\">\n {filtered.filter((e) => e.type === 'assignment').length}\n </span>\n </div>\n </CardContent>\n </Card>\n </div>\n\n <div className=\"lg:col-span-9 space-y-6\">\n {sortedDates.length === 0 ? (\n <Card>\n <CardContent className=\"py-16 text-center\">\n <CalendarIcon className=\"h-12 w-12 mx-auto mb-3 text-muted-foreground\" />\n <p className=\"text-muted-foreground\">\n {t(\n 'buildmyiq.calendar.emptyState',\n 'No events found. Try adjusting your filters.'\n )}\n </p>\n </CardContent>\n </Card>\n ) : (\n sortedDates.map((date) => (\n <div key={date}>\n <div className=\"flex items-center gap-2 mb-3\">\n <h2 className=\"text-lg font-semibold\">\n {new Date(date).toLocaleDateString('en-US', {\n weekday: 'long',\n month: 'long',\n day: 'numeric',\n year: 'numeric',\n })}\n </h2>\n <Badge variant=\"secondary\">\n {eventsByDate[date].length}{' '}\n {eventsByDate[date].length !== 1\n ? t('buildmyiq.calendar.eventCount.plural', 'events')\n : t('buildmyiq.calendar.eventCount.singular', 'event')}\n </Badge>\n </div>\n <div className=\"space-y-3\">\n {eventsByDate[date].map((evt) => {\n const cfg = typeConfig[evt.type];\n return (\n <Card key={evt.id} className=\"hover:shadow-md transition-shadow\">\n <CardContent className=\"py-4\">\n <div className=\"flex items-start gap-4\">\n <div\n className={`rounded-lg p-2 ${cfg.color.split(' ').slice(0, 1).join(' ')}`}\n >\n <cfg.icon\n className={`h-5 w-5 ${cfg.color.split(' ').slice(1).join(' ')}`}\n />\n </div>\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-2 mb-1\">\n <h3 className=\"font-medium\">{evt.title}</h3>\n <Badge className={cfg.color}>{cfg.label}</Badge>\n </div>\n <p className=\"text-sm text-muted-foreground mb-2\">{evt.course}</p>\n <div className=\"flex items-center gap-4 text-sm text-muted-foreground\">\n <div className=\"flex items-center gap-1\">\n <Clock className=\"h-4 w-4\" />\n {evt.time}\n </div>\n <div className=\"flex items-center gap-1\">\n <MapPin className=\"h-4 w-4\" />\n {evt.location}\n </div>\n </div>\n </div>\n </div>\n </CardContent>\n </Card>\n );\n })}\n </div>\n </div>\n ))\n )}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function CommunicationAnnouncementsPagePage(): import("react/jsx-runtime").JSX.Element;
2
+ //# sourceMappingURL=CommunicationAnnouncementsPagePage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommunicationAnnouncementsPagePage.d.ts","sourceRoot":"","sources":["../../../src/buildmyiq/pages/CommunicationAnnouncementsPagePage.tsx"],"names":[],"mappings":"AAaA,wBAAgB,kCAAkC,4CAqKjD"}
@@ -0,0 +1,180 @@
1
+ import { useBuildMyIQStore as e } from "../store/buildmyiqStore.js";
2
+ import { useState as t } from "react";
3
+ import { Bell as n, CheckCheck as r, ChevronDown as i, ChevronUp as a, Megaphone as o, Pin as s, Plus as c } from "lucide-react";
4
+ import { jsx as l, jsxs as u } from "react/jsx-runtime";
5
+ import { Badge as d, Button as f, Card as p, CardContent as m } from "@burdenoff/fe-libs/ui";
6
+ //#region src/buildmyiq/pages/CommunicationAnnouncementsPagePage.tsx
7
+ var h = {
8
+ high: "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400",
9
+ medium: "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400",
10
+ low: "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400"
11
+ };
12
+ function g() {
13
+ let { announcements: g, markAnnouncementRead: _ } = e(), [v, y] = t("all"), [b, x] = t("all"), [S, C] = t(null), w = ["all", ...Array.from(new Set(g.map((e) => e.course)))], T = g.filter((e) => {
14
+ let t = v === "all" || e.priority === v, n = b === "all" || e.course === b;
15
+ return t && n;
16
+ }).sort((e, t) => e.pinned === t.pinned ? new Date(t.timestamp).getTime() - new Date(e.timestamp).getTime() : e.pinned ? -1 : 1), E = g.filter((e) => e.unread).length;
17
+ return /* @__PURE__ */ u("div", {
18
+ className: "space-y-6 p-6",
19
+ children: [
20
+ /* @__PURE__ */ u("div", {
21
+ className: "flex items-center justify-between",
22
+ children: [/* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("h1", {
23
+ className: "text-2xl font-semibold",
24
+ children: "Announcements"
25
+ }), /* @__PURE__ */ l("p", {
26
+ className: "text-sm text-muted-foreground",
27
+ children: E > 0 ? `${E} unread announcements` : "All caught up"
28
+ })] }), /* @__PURE__ */ u("div", {
29
+ className: "flex gap-2",
30
+ children: [E > 0 && /* @__PURE__ */ u(f, {
31
+ variant: "outline",
32
+ size: "sm",
33
+ onClick: () => {
34
+ g.filter((e) => e.unread).forEach((e) => _(e.id));
35
+ },
36
+ children: [/* @__PURE__ */ l(r, { className: "mr-2 h-4 w-4" }), "Mark All Read"]
37
+ }), /* @__PURE__ */ u(f, {
38
+ size: "sm",
39
+ children: [/* @__PURE__ */ l(c, { className: "mr-2 h-4 w-4" }), "New Announcement"]
40
+ })]
41
+ })]
42
+ }),
43
+ /* @__PURE__ */ u("div", {
44
+ className: "grid grid-cols-1 md:grid-cols-3 gap-4",
45
+ children: [
46
+ /* @__PURE__ */ l(p, { children: /* @__PURE__ */ u(m, {
47
+ className: "pt-6",
48
+ children: [/* @__PURE__ */ l("p", {
49
+ className: "text-sm text-muted-foreground",
50
+ children: "Total"
51
+ }), /* @__PURE__ */ l("p", {
52
+ className: "text-2xl font-bold",
53
+ children: g.length
54
+ })]
55
+ }) }),
56
+ /* @__PURE__ */ l(p, { children: /* @__PURE__ */ u(m, {
57
+ className: "pt-6",
58
+ children: [/* @__PURE__ */ l("p", {
59
+ className: "text-sm text-muted-foreground",
60
+ children: "Unread"
61
+ }), /* @__PURE__ */ l("p", {
62
+ className: "text-2xl font-bold text-red-600",
63
+ children: E
64
+ })]
65
+ }) }),
66
+ /* @__PURE__ */ l(p, { children: /* @__PURE__ */ u(m, {
67
+ className: "pt-6",
68
+ children: [/* @__PURE__ */ l("p", {
69
+ className: "text-sm text-muted-foreground",
70
+ children: "High Priority"
71
+ }), /* @__PURE__ */ l("p", {
72
+ className: "text-2xl font-bold text-orange-600",
73
+ children: g.filter((e) => e.priority === "high").length
74
+ })]
75
+ }) })
76
+ ]
77
+ }),
78
+ /* @__PURE__ */ u("div", {
79
+ className: "flex flex-col sm:flex-row gap-3",
80
+ children: [/* @__PURE__ */ l("div", {
81
+ className: "flex gap-1",
82
+ children: [
83
+ "all",
84
+ "high",
85
+ "medium",
86
+ "low"
87
+ ].map((e) => /* @__PURE__ */ l(f, {
88
+ variant: v === e ? "default" : "outline",
89
+ size: "sm",
90
+ className: "capitalize",
91
+ onClick: () => y(e),
92
+ children: e === "all" ? "All Priorities" : e
93
+ }, e))
94
+ }), /* @__PURE__ */ l("select", {
95
+ value: b,
96
+ onChange: (e) => x(e.target.value),
97
+ className: "h-9 rounded-md border border-input bg-background px-3 text-sm",
98
+ children: w.map((e) => /* @__PURE__ */ l("option", {
99
+ value: e,
100
+ children: e === "all" ? "All Courses" : e
101
+ }, e))
102
+ })]
103
+ }),
104
+ /* @__PURE__ */ l("div", {
105
+ className: "space-y-3",
106
+ children: T.length === 0 ? /* @__PURE__ */ l(p, { children: /* @__PURE__ */ u(m, {
107
+ className: "py-12 text-center",
108
+ children: [/* @__PURE__ */ l(o, { className: "h-12 w-12 mx-auto mb-3 text-muted-foreground" }), /* @__PURE__ */ l("p", {
109
+ className: "text-muted-foreground",
110
+ children: "No announcements match your filters"
111
+ })]
112
+ }) }) : T.map((e) => /* @__PURE__ */ l(p, {
113
+ className: `cursor-pointer hover:shadow-md transition-shadow ${e.unread ? "border-l-4 border-l-blue-500" : ""}`,
114
+ onClick: () => {
115
+ C(S === e.id ? null : e.id), e.unread && _(e.id);
116
+ },
117
+ children: /* @__PURE__ */ l(m, {
118
+ className: "py-4",
119
+ children: /* @__PURE__ */ u("div", {
120
+ className: "flex items-start gap-3",
121
+ children: [
122
+ e.pinned && /* @__PURE__ */ l(s, { className: "h-4 w-4 text-blue-500 shrink-0 mt-1" }),
123
+ e.unread && !e.pinned && /* @__PURE__ */ l(n, { className: "h-4 w-4 text-red-500 shrink-0 mt-1" }),
124
+ !e.pinned && !e.unread && /* @__PURE__ */ l(o, { className: "h-4 w-4 text-muted-foreground shrink-0 mt-1" }),
125
+ /* @__PURE__ */ u("div", {
126
+ className: "flex-1 min-w-0",
127
+ children: [
128
+ /* @__PURE__ */ u("div", {
129
+ className: "flex items-center gap-2 flex-wrap mb-1",
130
+ children: [
131
+ /* @__PURE__ */ l("h3", {
132
+ className: `font-medium ${e.unread ? "font-bold" : ""}`,
133
+ children: e.title
134
+ }),
135
+ /* @__PURE__ */ l(d, {
136
+ className: h[e.priority],
137
+ children: e.priority
138
+ }),
139
+ e.pinned && /* @__PURE__ */ l(d, {
140
+ variant: "outline",
141
+ className: "text-xs",
142
+ children: "Pinned"
143
+ })
144
+ ]
145
+ }),
146
+ /* @__PURE__ */ u("div", {
147
+ className: "flex items-center gap-2 text-xs text-muted-foreground mb-2",
148
+ children: [
149
+ /* @__PURE__ */ l("span", { children: e.author }),
150
+ /* @__PURE__ */ l("span", { children: "-" }),
151
+ /* @__PURE__ */ l("span", { children: e.course }),
152
+ /* @__PURE__ */ l("span", { children: "-" }),
153
+ /* @__PURE__ */ l("span", { children: new Date(e.timestamp).toLocaleDateString() })
154
+ ]
155
+ }),
156
+ S === e.id ? /* @__PURE__ */ l("p", {
157
+ className: "text-sm text-muted-foreground",
158
+ children: e.content
159
+ }) : /* @__PURE__ */ l("p", {
160
+ className: "text-sm text-muted-foreground truncate",
161
+ children: e.content
162
+ })
163
+ ]
164
+ }),
165
+ /* @__PURE__ */ l("div", {
166
+ className: "shrink-0",
167
+ children: S === e.id ? /* @__PURE__ */ l(a, { className: "h-4 w-4 text-muted-foreground" }) : /* @__PURE__ */ l(i, { className: "h-4 w-4 text-muted-foreground" })
168
+ })
169
+ ]
170
+ })
171
+ })
172
+ }, e.id))
173
+ })
174
+ ]
175
+ });
176
+ }
177
+ //#endregion
178
+ export { g as CommunicationAnnouncementsPagePage };
179
+
180
+ //# sourceMappingURL=CommunicationAnnouncementsPagePage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommunicationAnnouncementsPagePage.js","names":[],"sources":["../../../src/buildmyiq/pages/CommunicationAnnouncementsPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { Badge, Button, Card, CardContent, CardHeader, CardTitle } from '@burdenoff/fe-libs/ui';\nimport { Megaphone, Pin, Bell, CheckCheck, Plus, ChevronDown, ChevronUp } from 'lucide-react';\nimport { useBuildMyIQStore } from '../store/buildmyiqStore';\n\ntype Priority = 'all' | 'high' | 'medium' | 'low';\n\nconst priorityColors: Record<string, string> = {\n high: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400',\n medium: 'bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400',\n low: 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400',\n};\n\nexport function CommunicationAnnouncementsPagePage() {\n const { announcements, markAnnouncementRead } = useBuildMyIQStore();\n const [priorityFilter, setPriorityFilter] = useState<Priority>('all');\n const [courseFilter, setCourseFilter] = useState('all');\n const [expandedId, setExpandedId] = useState<string | null>(null);\n\n const courses = ['all', ...Array.from(new Set(announcements.map((a) => a.course)))];\n\n const filtered = announcements\n .filter((a) => {\n const matchesPriority = priorityFilter === 'all' || a.priority === priorityFilter;\n const matchesCourse = courseFilter === 'all' || a.course === courseFilter;\n return matchesPriority && matchesCourse;\n })\n .sort((a, b) => {\n if (a.pinned !== b.pinned) return a.pinned ? -1 : 1;\n return new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime();\n });\n\n const unreadCount = announcements.filter((a) => a.unread).length;\n\n const markAllRead = () => {\n announcements.filter((a) => a.unread).forEach((a) => markAnnouncementRead(a.id));\n };\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Announcements</h1>\n <p className=\"text-sm text-muted-foreground\">\n {unreadCount > 0 ? `${unreadCount} unread announcements` : 'All caught up'}\n </p>\n </div>\n <div className=\"flex gap-2\">\n {unreadCount > 0 && (\n <Button variant=\"outline\" size=\"sm\" onClick={markAllRead}>\n <CheckCheck className=\"mr-2 h-4 w-4\" />\n Mark All Read\n </Button>\n )}\n <Button size=\"sm\">\n <Plus className=\"mr-2 h-4 w-4\" />\n New Announcement\n </Button>\n </div>\n </div>\n\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\n <Card>\n <CardContent className=\"pt-6\">\n <p className=\"text-sm text-muted-foreground\">Total</p>\n <p className=\"text-2xl font-bold\">{announcements.length}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-6\">\n <p className=\"text-sm text-muted-foreground\">Unread</p>\n <p className=\"text-2xl font-bold text-red-600\">{unreadCount}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-6\">\n <p className=\"text-sm text-muted-foreground\">High Priority</p>\n <p className=\"text-2xl font-bold text-orange-600\">\n {announcements.filter((a) => a.priority === 'high').length}\n </p>\n </CardContent>\n </Card>\n </div>\n\n <div className=\"flex flex-col sm:flex-row gap-3\">\n <div className=\"flex gap-1\">\n {(['all', 'high', 'medium', 'low'] as Priority[]).map((p) => (\n <Button\n key={p}\n variant={priorityFilter === p ? 'default' : 'outline'}\n size=\"sm\"\n className=\"capitalize\"\n onClick={() => setPriorityFilter(p)}\n >\n {p === 'all' ? 'All Priorities' : p}\n </Button>\n ))}\n </div>\n <select\n value={courseFilter}\n onChange={(e) => setCourseFilter(e.target.value)}\n className=\"h-9 rounded-md border border-input bg-background px-3 text-sm\"\n >\n {courses.map((c) => (\n <option key={c} value={c}>\n {c === 'all' ? 'All Courses' : c}\n </option>\n ))}\n </select>\n </div>\n\n <div className=\"space-y-3\">\n {filtered.length === 0 ? (\n <Card>\n <CardContent className=\"py-12 text-center\">\n <Megaphone className=\"h-12 w-12 mx-auto mb-3 text-muted-foreground\" />\n <p className=\"text-muted-foreground\">No announcements match your filters</p>\n </CardContent>\n </Card>\n ) : (\n filtered.map((ann) => (\n <Card\n key={ann.id}\n className={`cursor-pointer hover:shadow-md transition-shadow ${ann.unread ? 'border-l-4 border-l-blue-500' : ''}`}\n onClick={() => {\n setExpandedId(expandedId === ann.id ? null : ann.id);\n if (ann.unread) markAnnouncementRead(ann.id);\n }}\n >\n <CardContent className=\"py-4\">\n <div className=\"flex items-start gap-3\">\n {ann.pinned && <Pin className=\"h-4 w-4 text-blue-500 shrink-0 mt-1\" />}\n {ann.unread && !ann.pinned && (\n <Bell className=\"h-4 w-4 text-red-500 shrink-0 mt-1\" />\n )}\n {!ann.pinned && !ann.unread && (\n <Megaphone className=\"h-4 w-4 text-muted-foreground shrink-0 mt-1\" />\n )}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 flex-wrap mb-1\">\n <h3 className={`font-medium ${ann.unread ? 'font-bold' : ''}`}>\n {ann.title}\n </h3>\n <Badge className={priorityColors[ann.priority]}>{ann.priority}</Badge>\n {ann.pinned && (\n <Badge variant=\"outline\" className=\"text-xs\">\n Pinned\n </Badge>\n )}\n </div>\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground mb-2\">\n <span>{ann.author}</span>\n <span>-</span>\n <span>{ann.course}</span>\n <span>-</span>\n <span>{new Date(ann.timestamp).toLocaleDateString()}</span>\n </div>\n {expandedId === ann.id ? (\n <p className=\"text-sm text-muted-foreground\">{ann.content}</p>\n ) : (\n <p className=\"text-sm text-muted-foreground truncate\">{ann.content}</p>\n )}\n </div>\n <div className=\"shrink-0\">\n {expandedId === ann.id ? (\n <ChevronUp className=\"h-4 w-4 text-muted-foreground\" />\n ) : (\n <ChevronDown className=\"h-4 w-4 text-muted-foreground\" />\n )}\n </div>\n </div>\n </CardContent>\n </Card>\n ))\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;AAOA,IAAM,IAAyC;CAC7C,MAAM;CACN,QAAQ;CACR,KAAK;CACN;AAED,SAAgB,IAAqC;CACnD,IAAM,EAAE,kBAAe,4BAAyB,GAAmB,EAC7D,CAAC,GAAgB,KAAqB,EAAmB,MAAM,EAC/D,CAAC,GAAc,KAAmB,EAAS,MAAM,EACjD,CAAC,GAAY,KAAiB,EAAwB,KAAK,EAE3D,IAAU,CAAC,OAAO,GAAG,MAAM,KAAK,IAAI,IAAI,EAAc,KAAK,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAE7E,IAAW,EACd,QAAQ,MAAM;EACb,IAAM,IAAkB,MAAmB,SAAS,EAAE,aAAa,GAC7D,IAAgB,MAAiB,SAAS,EAAE,WAAW;AAC7D,SAAO,KAAmB;GAC1B,CACD,MAAM,GAAG,MACJ,EAAE,WAAW,EAAE,SACZ,IAAI,KAAK,EAAE,UAAU,CAAC,SAAS,GAAG,IAAI,KAAK,EAAE,UAAU,CAAC,SAAS,GADtC,EAAE,SAAS,KAAK,EAElD,EAEE,IAAc,EAAc,QAAQ,MAAM,EAAE,OAAO,CAAC;AAM1D,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;eAAyB;KAAkB,CAAA,EACzD,kBAAC,KAAD;KAAG,WAAU;eACV,IAAc,IAAI,GAAG,EAAY,yBAAyB;KACzD,CAAA,CACA,EAAA,CAAA,EACN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACG,IAAc,KACb,kBAAC,GAAD;MAAQ,SAAQ;MAAU,MAAK;MAAK,eAfpB;AACxB,SAAc,QAAQ,MAAM,EAAE,OAAO,CAAC,SAAS,MAAM,EAAqB,EAAE,GAAG,CAAC;;gBAcxE,CACE,kBAAC,GAAD,EAAY,WAAU,gBAAiB,CAAA,EAAA,gBAEhC;SAEX,kBAAC,GAAD;MAAQ,MAAK;gBAAb,CACE,kBAAC,GAAD,EAAM,WAAU,gBAAiB,CAAA,EAAA,mBAE1B;QACL;OACF;;GAEN,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;MAAa,WAAU;gBAAvB,CACE,kBAAC,KAAD;OAAG,WAAU;iBAAgC;OAAS,CAAA,EACtD,kBAAC,KAAD;OAAG,WAAU;iBAAsB,EAAc;OAAW,CAAA,CAChD;SACT,CAAA;KACP,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;MAAa,WAAU;gBAAvB,CACE,kBAAC,KAAD;OAAG,WAAU;iBAAgC;OAAU,CAAA,EACvD,kBAAC,KAAD;OAAG,WAAU;iBAAmC;OAAgB,CAAA,CACpD;SACT,CAAA;KACP,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;MAAa,WAAU;gBAAvB,CACE,kBAAC,KAAD;OAAG,WAAU;iBAAgC;OAAiB,CAAA,EAC9D,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAc,QAAQ,MAAM,EAAE,aAAa,OAAO,CAAC;OAClD,CAAA,CACQ;SACT,CAAA;KACH;;GAEN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eACX;MAAC;MAAO;MAAQ;MAAU;MAAM,CAAgB,KAAK,MACrD,kBAAC,GAAD;MAEE,SAAS,MAAmB,IAAI,YAAY;MAC5C,MAAK;MACL,WAAU;MACV,eAAe,EAAkB,EAAE;gBAElC,MAAM,QAAQ,mBAAmB;MAC3B,EAPF,EAOE,CACT;KACE,CAAA,EACN,kBAAC,UAAD;KACE,OAAO;KACP,WAAW,MAAM,EAAgB,EAAE,OAAO,MAAM;KAChD,WAAU;eAET,EAAQ,KAAK,MACZ,kBAAC,UAAD;MAAgB,OAAO;gBACpB,MAAM,QAAQ,gBAAgB;MACxB,EAFI,EAEJ,CACT;KACK,CAAA,CACL;;GAEN,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAS,WAAW,IACnB,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;KAAa,WAAU;eAAvB,CACE,kBAAC,GAAD,EAAW,WAAU,gDAAiD,CAAA,EACtE,kBAAC,KAAD;MAAG,WAAU;gBAAwB;MAAuC,CAAA,CAChE;QACT,CAAA,GAEP,EAAS,KAAK,MACZ,kBAAC,GAAD;KAEE,WAAW,oDAAoD,EAAI,SAAS,iCAAiC;KAC7G,eAAe;AAEb,MADA,EAAc,MAAe,EAAI,KAAK,OAAO,EAAI,GAAG,EAChD,EAAI,UAAQ,EAAqB,EAAI,GAAG;;eAG9C,kBAAC,GAAD;MAAa,WAAU;gBACrB,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACG,EAAI,UAAU,kBAAC,GAAD,EAAK,WAAU,uCAAwC,CAAA;QACrE,EAAI,UAAU,CAAC,EAAI,UAClB,kBAAC,GAAD,EAAM,WAAU,sCAAuC,CAAA;QAExD,CAAC,EAAI,UAAU,CAAC,EAAI,UACnB,kBAAC,GAAD,EAAW,WAAU,+CAAgD,CAAA;QAEvE,kBAAC,OAAD;SAAK,WAAU;mBAAf;UACE,kBAAC,OAAD;WAAK,WAAU;qBAAf;YACE,kBAAC,MAAD;aAAI,WAAW,eAAe,EAAI,SAAS,cAAc;uBACtD,EAAI;aACF,CAAA;YACL,kBAAC,GAAD;aAAO,WAAW,EAAe,EAAI;uBAAY,EAAI;aAAiB,CAAA;YACrE,EAAI,UACH,kBAAC,GAAD;aAAO,SAAQ;aAAU,WAAU;uBAAU;aAErC,CAAA;YAEN;;UACN,kBAAC,OAAD;WAAK,WAAU;qBAAf;YACE,kBAAC,QAAD,EAAA,UAAO,EAAI,QAAc,CAAA;YACzB,kBAAC,QAAD,EAAA,UAAM,KAAQ,CAAA;YACd,kBAAC,QAAD,EAAA,UAAO,EAAI,QAAc,CAAA;YACzB,kBAAC,QAAD,EAAA,UAAM,KAAQ,CAAA;YACd,kBAAC,QAAD,EAAA,UAAO,IAAI,KAAK,EAAI,UAAU,CAAC,oBAAoB,EAAQ,CAAA;YACvD;;UACL,MAAe,EAAI,KAClB,kBAAC,KAAD;WAAG,WAAU;qBAAiC,EAAI;WAAY,CAAA,GAE9D,kBAAC,KAAD;WAAG,WAAU;qBAA0C,EAAI;WAAY,CAAA;UAErE;;QACN,kBAAC,OAAD;SAAK,WAAU;mBACZ,MAAe,EAAI,KAClB,kBAAC,GAAD,EAAW,WAAU,iCAAkC,CAAA,GAEvD,kBAAC,GAAD,EAAa,WAAU,iCAAkC,CAAA;SAEvD,CAAA;QACF;;MACM,CAAA;KACT,EAlDA,EAAI,GAkDJ,CACP;IAEA,CAAA;GACF"}
@@ -0,0 +1,2 @@
1
+ export declare function CommunicationForumsPagePage(): import("react/jsx-runtime").JSX.Element;
2
+ //# sourceMappingURL=CommunicationForumsPagePage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommunicationForumsPagePage.d.ts","sourceRoot":"","sources":["../../../src/buildmyiq/pages/CommunicationForumsPagePage.tsx"],"names":[],"mappings":"AAeA,wBAAgB,2BAA2B,4CA2H1C"}