11<script setup lang="ts">
2- import { ref } from " vue" ;
2+ import { ref , reactive } from " vue" ;
33import { useAuthStore } from " ../../stores/auth" ;
44import { useRouter } from " vue-router" ;
55import MyStudiesItem from " ./components/MyStudiesItem.vue" ;
66import StudyDetailsSidebar from " ./components/StudyDetailsSideBar.vue" ;
77import { useQuery , useMutation , useQueryClient } from " @tanstack/vue-query" ;
8+ import authAPI from " @/api/auth" ;
89import studiesAPI from " @/api/studies" ;
910import AppButton from " @/components/ui/AppButton.vue" ;
1011import RecentStudies from " ./components/RecentStudies.vue" ;
12+ import { ElDialog , ElForm , ElFormItem , ElInput , ElTag } from " element-plus" ;
13+ import { Plus } from " @element-plus/icons-vue" ;
1114
1215const router = useRouter ();
1316const authStore = useAuthStore ();
@@ -33,6 +36,18 @@ const { mutate, isLoading } = useMutation({
3336
3437const selectedStudyId = ref <string | null >(null );
3538const showSidebar = ref <boolean >(false );
39+ const createStudyPopup = ref (false );
40+ const { data : currentUser } = useQuery ({
41+ queryKey: [" user" ],
42+ queryFn: authAPI .getCurrentUser ,
43+ });
44+
45+ const tagsIcon = {
46+ Cognitive: " /brain.svg" ,
47+ Hearing: " /hearing.svg" ,
48+ Training: " /training.svg" ,
49+ Vision: " /vision.svg" ,
50+ };
3651
3752const openSidebar = (studyId : string ) => {
3853 selectedStudyId .value = studyId ;
@@ -43,8 +58,40 @@ const handleStudyDeleted = async () => {
4358 await refetch ();
4459 await queryClient .invalidateQueries ({ queryKey: [" studies" , " recent" ] });
4560};
46- </script >
4761
62+ const firstStudyForm = reactive ({
63+ title: " " ,
64+ description: " " ,
65+ tags: [] as string [],
66+ serverCode: " " ,
67+ });
68+
69+ const createFirstStudy = async () => {
70+ createStudyPopup .value = false ;
71+ const createdStudyId = await studiesAPI .createStudy ();
72+ const study = await studiesAPI .getStudy (createdStudyId );
73+ await studiesAPI .saveStudy (createdStudyId , {
74+ ... study ,
75+ name: firstStudyForm .title ,
76+ description: firstStudyForm .description ,
77+ variants: study .variants .map ((variant , index ) =>
78+ index === 0
79+ ? {
80+ ... variant ,
81+ serverCode: firstStudyForm .serverCode ,
82+ tags: firstStudyForm .tags ,
83+ }
84+ : variant
85+ ),
86+ });
87+ router .push ({ name: " study" , params: { id: createdStudyId } });
88+ };
89+
90+ const updateWizardSteps = async (step : number ) => {
91+ await authAPI .updateCurrentUser ({ welcomeWizardStep: step });
92+ await queryClient .invalidateQueries ([" user" ]);
93+ };
94+ </script >
4895<template >
4996 <div
5097 v-loading =" isLoading"
@@ -53,8 +100,203 @@ const handleStudyDeleted = async () => {
53100 <div class =" flex items-center" >
54101 <h1 class =" text-3xl font-bold mb-4 -mt-4" >My Studies</h1 >
55102 <div class =" flex-1" ></div >
56- <AppButton class="mb-4 -mt-4" @click =" mutate " >+ New</AppButton >
103+ <el-popover
104+ title =" Create a new Study"
105+ placement =" left-start"
106+ width =" 308px"
107+ popper-style =" border-radius: 10px; z-index: 1500"
108+ :hide-after =" 0"
109+ :visible =" currentUser?.welcomeWizardStep == 0"
110+ trigger =" manual"
111+ >
112+ <template #default >
113+ Press the “New” button to create a new study
114+ <div
115+ style ="
116+ display : flex ;
117+ justify-content : space-between ;
118+ align-items : center ;
119+ margin-top : 8px ;
120+ "
121+ >
122+ <el-button
123+ class =" close-tip"
124+ style ="
125+ width : 59px ;
126+ height : 36px ;
127+ border-radius : 10px ;
128+ border-width : 1px ;
129+ border-color : #c3bcb5 ;
130+ background-color : #fffdfd ;
131+ font-size : 14px ;
132+ font-weight : 700 ;
133+ "
134+ @click ="
135+ updateWizardSteps((currentUser?.welcomeWizardStep ?? 0) + 1)
136+ "
137+ >Close</el-button
138+ >
139+ <div style =" font-weight : 500 ; font-size : 14px " >1/3</div >
140+ <el-button
141+ type =" text"
142+ style =" font-size : 14px ; font-weight : 500 ; color : #8a7f75 "
143+ @click =" updateWizardSteps(3)"
144+ >Skip all tips</el-button
145+ >
146+ </div >
147+ </template >
148+ <template #reference >
149+ <AppButton
150+ class="mb-4 -mt-4"
151+ @click ="
152+ if (currentUser ?.welcomeWizardStep == 1 ) createStudyPopup = true ;
153+ else mutate ();
154+ "
155+ >+ New</AppButton
156+ >
157+ </template >
158+ </el-popover >
159+ <div
160+ v-if =" currentUser?.welcomeWizardStep == 0"
161+ style =" position : fixed ; inset : 0 ; background : rgba (0 , 0 , 0 , 0.5 )"
162+ ></div >
57163 </div >
164+ <ElDialog
165+ v-model =" createStudyPopup "
166+ width="545px"
167+ style =" border-radius : 30px ; background-color : #fffdfd "
168+ >
169+ <ElForm
170+ :model =" firstStudyForm "
171+ label-position="top"
172+ style =" margin-right : 30px ; margin-left : 30px "
173+ >
174+ <ElFormItem label="Title">
175+ <template #label >
176+ <span
177+ class =" font-bold text-base text-black"
178+ style =" font-size : 16px "
179+ >
180+ Title
181+ </span >
182+ </template >
183+ <ElInput
184+ v-model =" firstStudyForm .title "
185+ style =" height : 44px ; border-radius : 10px "
186+ />
187+ </ElFormItem >
188+ <h1
189+ class =" inline-block border-b-2 border-red-500 pb-1 mb-4 font-bold text-black"
190+ style =" font-size : 14px "
191+ >
192+ Details
193+ </h1 >
194+ <ElFormItem label="Description">
195+ <template #label >
196+ <span class =" font-bold text-base text-black" > Description </span >
197+ </template >
198+ <ElInput
199+ v-model =" firstStudyForm .description "
200+ type="textarea"
201+ style =" height : 88px "
202+ :rows =" 4 "
203+ resize="none"
204+ />
205+ </ElFormItem >
206+ <ElFormItem label="Condition Server Code">
207+ <template #label >
208+ <span class =" font-bold text-base text-black" >
209+ Condition Server Code
210+ </span >
211+ </template >
212+ <ElInput
213+ v-model =" firstStudyForm .serverCode "
214+ style =" width : 165px ; border-radius : 10px ; background-color : #fffdfd "
215+ />
216+ </ElFormItem >
217+ <ElFormItem label="Tags">
218+ <template #label >
219+ <span class =" font-bold text-base text-black" > Tags </span >
220+ </template >
221+ <ElTag
222+ v-for =" tag in firstStudyForm .tags "
223+ :key =" tag "
224+ closable
225+ style ="
226+ margin-right : 4px ;
227+ border-color : #ffb9aa ;
228+ background-color : #ffede9 ;
229+ color : #ba3b2a ;
230+ "
231+ @close ="
232+ firstStudyForm .tags = firstStudyForm .tags .filter ((t ) => t !== tag )
233+ "
234+ >
235+ <img
236+ :src =" tagsIcon[tag as keyof typeof tagsIcon]"
237+ class =" inline-block mr-2"
238+ style =" width : 12px ; height : 12px "
239+ />{{ tag }}
240+ </ElTag >
241+ <el-dropdown trigger =" click" >
242+ <el-button
243+ style ="
244+ width : 20px ;
245+ height : 20px ;
246+ padding : 0 ;
247+ border-radius : 6px ;
248+ background-color : #fcf9f7 ;
249+ "
250+ >
251+ <template #icon >
252+ <Plus />
253+ </template >
254+ </el-button >
255+ <template #dropdown >
256+ <el-dropdown-menu >
257+ <el-dropdown-item
258+ v-for =" tag in Object.keys(tagsIcon)"
259+ :key =" tag"
260+ >
261+ <el-checkbox
262+ :model-value =" firstStudyForm.tags.includes(tag)"
263+ class =" tag-checkbox"
264+ @change ="
265+ (checked: boolean) => {
266+ if (checked) {
267+ firstStudyForm.tags.push(tag);
268+ } else {
269+ firstStudyForm.tags = firstStudyForm.tags.filter(
270+ (t) => t !== tag
271+ );
272+ }
273+ }
274+ "
275+ >
276+ {{ tag }}
277+ </el-checkbox >
278+ </el-dropdown-item >
279+ </el-dropdown-menu >
280+ </template >
281+ </el-dropdown >
282+ </ElFormItem >
283+ </ElForm >
284+ <template #footer >
285+ <el-button
286+ style ="
287+ width : 105px ;
288+ height : 36px ;
289+ border-radius : 10px ;
290+ border-color : #c3bcb5 ;
291+ font-weight : 700 ;
292+ "
293+ class =" block mx-auto w-fit"
294+ @click =" createFirstStudy"
295+ >Create Study</el-button
296+ >
297+ </template >
298+ </ElDialog >
299+
58300 <h1 class =" mt-4" >Recents</h1 >
59301 <RecentStudies />
60302
@@ -102,3 +344,22 @@ const handleStudyDeleted = async () => {
102344 @close =" showSidebar = false "
103345 />
104346</template >
347+
348+ <style scoped>
349+ :deep(.el-input__wrapper ),
350+ :deep(.el-textarea__inner ) {
351+ border-radius : 10px !important ;
352+ background-color : #fffdfd !important ;
353+ }
354+ :deep(.el-tag__close ) {
355+ color : #ba3b2a !important ;
356+ background-color : transparent !important ;
357+ }
358+ :deep(.el-dialog__footer .el-button :hover ) {
359+ color : inherit !important ;
360+ background-color : #f5f5f5 !important ;
361+ }
362+ :deep(.tag-checkbox.is-checked .el-checkbox__label ) {
363+ color : inherit !important ;
364+ }
365+ </style >
0 commit comments