Skip to content
Toggle navigation
Projects
Groups
Snippets
Help
dtd
/
civitas.ui
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit ffdda07b
authored
a week ago
by
Samuel Taniel Mulyadi
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'staging' into 'master'
Staging See merge request
!10
2 parents
ae1865ce
a2f1917e
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
253 additions
and
9 deletions
components/beranda/UserJadwal.vue
views/dstipro/beranda/UserProfileHeader.vue
components/beranda/UserJadwal.vue
View file @
ffdda07
...
@@ -5,10 +5,23 @@ import { useKeycloakStore } from '@/@core/stores/keycloakStore'
...
@@ -5,10 +5,23 @@ import { useKeycloakStore } from '@/@core/stores/keycloakStore'
const
keycloakStore
=
useKeycloakStore
()
const
keycloakStore
=
useKeycloakStore
()
const
schedule
=
ref
<
any
[]
>
([])
const
schedule
=
ref
<
any
[]
>
([])
const
loading
=
ref
(
false
)
const
loading
=
ref
(
false
)
const
viewMode
=
ref
<
'vertical'
|
'horizontal'
>
(
'vertical'
)
// ← track the mode
const
daysOfWeek
=
[
'Senin'
,
'Selasa'
,
'Rabu'
,
'Kamis'
,
'Jumat'
]
const
daysOfWeek
=
[
'Senin'
,
'Selasa'
,
'Rabu'
,
'Kamis'
,
'Jumat'
]
const
startHour
=
7
const
startHour
=
7
const
endHour
=
21
const
endHour
=
21
const
currentTime
=
ref
(
new
Date
())
// Function to check if the current time is within a schedule item range
function
isCurrentScheduleItem
(
item
:
any
)
{
const
now
=
currentTime
.
value
const
startTime
=
parseTime
(
item
.
start
)
const
endTime
=
parseTime
(
item
.
end
)
const
currentMinutes
=
(
now
.
getHours
()
-
startHour
)
*
60
+
now
.
getMinutes
()
// Check if the current time is within the range (startTime < currentMinutes < endTime)
return
currentMinutes
>=
startTime
&&
currentMinutes
<=
endTime
}
async
function
getData
()
{
async
function
getData
()
{
loading
.
value
=
true
loading
.
value
=
true
...
@@ -40,6 +53,8 @@ async function getData() {
...
@@ -40,6 +53,8 @@ async function getData() {
lecturer
:
Object
.
values
(
course
.
PENGAJAR
).
join
(
', '
),
// Join multiple lecturers if exist
lecturer
:
Object
.
values
(
course
.
PENGAJAR
).
join
(
', '
),
// Join multiple lecturers if exist
room
:
jadwal
.
NM_RUANG
,
room
:
jadwal
.
NM_RUANG
,
building
:
jadwal
.
NM_GED
,
building
:
jadwal
.
NM_GED
,
tgl_mulai
:
jadwal
.
TGL_MULAI
,
tgl_selesai
:
jadwal
.
TGL_SELESAI
,
})),
})),
)
)
}
}
...
@@ -53,6 +68,8 @@ async function getData() {
...
@@ -53,6 +68,8 @@ async function getData() {
lecturer
:
item
.
NAMA_DOSEN
,
lecturer
:
item
.
NAMA_DOSEN
,
room
:
item
.
NM_RUANG
,
room
:
item
.
NM_RUANG
,
building
:
item
.
NM_GED
,
building
:
item
.
NM_GED
,
tgl_mulai
:
item
.
TGL_MULAI
,
tgl_selesai
:
item
.
TGL_SELESAI
,
}))
}))
}
}
else
if
(
keycloakStore
.
civitas
===
'staf'
)
{
else
if
(
keycloakStore
.
civitas
===
'staf'
)
{
...
@@ -97,14 +114,60 @@ function calculateRowSpan(start: string, end: string) {
...
@@ -97,14 +114,60 @@ function calculateRowSpan(start: string, end: string) {
return
rowSpan
return
rowSpan
}
}
// Group schedule by day
function
getScheduleByDay
(
day
:
string
)
{
return
schedule
.
value
.
filter
(
item
=>
item
.
day
===
day
)
}
// Get alternating color classes
function
getColorClass
(
index
:
number
)
{
const
colors
=
[
'red'
,
'blue'
,
'green'
]
return
`schedule-color-
${
colors
[
index
%
3
]}
`
}
</
script
>
</
script
>
<
template
>
<
template
>
<VCard
<VCard
class=
"timetable-card"
>
title=
"Jadwal Kuliah"
<template
#
title
>
class=
"timetable-card"
<div
class=
"d-flex align-center"
>
>
<!-- Left: Title -->
<VCard
class=
"timetable"
>
<span
class=
"me-auto"
>
Jadwal Kuliah
</span>
<!-- Right: Date Range Box -->
<div
class=
"me-auto date-range-box"
>
<span
v-if=
"schedule.length > 0"
>
{{
schedule
[
0
].
tgl_mulai
}}
/
{{
schedule
[
0
].
tgl_selesai
}}
</span>
</div>
<!-- Right: Icons -->
<div
class=
"d-flex gap-2"
>
<VBtn
icon
variant=
"text"
:color=
"viewMode === 'vertical' ? 'primary' : 'default'"
@
click=
"viewMode = 'vertical'"
>
<VIcon
icon=
"ri-layout-vertical-line"
/>
</VBtn>
<VBtn
icon
variant=
"text"
:color=
"viewMode === 'horizontal' ? 'primary' : 'default'"
@
click=
"viewMode = 'horizontal'"
>
<VIcon
icon=
"ri-layout-horizontal-line"
/>
</VBtn>
</div>
</div>
</
template
>
<VCard
v-if=
"viewMode === 'vertical'"
class=
"timetable"
>
<!-- Header Row -->
<!-- Header Row -->
<div
class=
"grid-header"
>
<div
class=
"grid-header"
>
<div
class=
"time-label"
>
<div
class=
"time-label"
>
...
@@ -173,10 +236,86 @@ function calculateRowSpan(start: string, end: string) {
...
@@ -173,10 +236,86 @@ function calculateRowSpan(start: string, end: string) {
</div>
</div>
</div>
</div>
</VCard>
</VCard>
<VCard
v-else
class=
"timetable px-4 py-6"
>
<table
class=
"w-100 text-left table-schedule fixed-table"
>
<thead>
<tr>
<th
v-for=
"day in daysOfWeek"
:key=
"day"
class=
"px-2 py-2"
>
{{ day }}
</th>
</tr>
</thead>
<tbody>
<tr
v-for=
"rowIndex in 10"
:key=
"`row-${rowIndex}`"
>
<td
v-for=
"(day, dayIndex) in daysOfWeek"
:key=
"day + rowIndex"
class=
"align-top px-2 py-3"
>
<div
v-if=
"getScheduleByDay(day)[rowIndex - 1]"
class=
"schedule-box"
:class=
"[getColorClass(rowIndex - 1)]"
>
<div
class=
"course-header mb-1"
>
<span
class=
"text-sm font-medium d-flex align-center gap-1"
>
<i
class=
"ri-time-line"
/>
{{
getScheduleByDay(day)[rowIndex - 1].start
}} - {{
getScheduleByDay(day)[rowIndex - 1].end
}}
</span>
<span
class=
"text-xs"
>
{{ getScheduleByDay(day)[rowIndex - 1].room }}
</span>
</div>
<div
class=
"course-title font-semibold text-sm mb-1"
>
<span
v-if=
"getScheduleByDay(day)[rowIndex - 1].course.includes('-')"
style=
"text-decoration: underline;"
>
{{ getScheduleByDay(day)[rowIndex - 1].course.split(' - ')[0] }}
</span>
<span
class=
"text-sm"
>
{{
getScheduleByDay(day)[rowIndex - 1].course.includes('-')
? getScheduleByDay(day)[rowIndex - 1].course.split(' - ')[1]
: getScheduleByDay(day)[rowIndex - 1].course
}}
</span>
</div>
<div
class=
"text-xs"
>
{{ getScheduleByDay(day)[rowIndex - 1].building }}
</div>
</div>
</td>
</tr>
</tbody>
</table>
</VCard>
</VCard>
</VCard>
</template>
</template>
<
style
scoped
>
<
style
scoped
>
.date-range-box
{
display
:
inline-block
;
border-radius
:
5px
;
background-color
:
rgba
(
var
(
--v-global-theme-primary
),
0.1
);
font-size
:
14px
;
font-weight
:
bold
;
margin-inline-start
:
10px
;
padding-block
:
5px
;
padding-inline
:
10px
;
}
.timetable
{
.timetable
{
display
:
flex
;
display
:
flex
;
flex-direction
:
column
;
flex-direction
:
column
;
...
@@ -219,6 +358,7 @@ function calculateRowSpan(start: string, end: string) {
...
@@ -219,6 +358,7 @@ function calculateRowSpan(start: string, end: string) {
.course-prefix
{
.course-prefix
{
color
:
color-mix
(
in
srgb
,
rgba
(
var
(
--v-global-theme-primary
))
70%
,
black
30%
);
color
:
color-mix
(
in
srgb
,
rgba
(
var
(
--v-global-theme-primary
))
70%
,
black
30%
);
text-decoration
:
underline
;
}
}
.grid-body
{
.grid-body
{
...
@@ -248,13 +388,14 @@ function calculateRowSpan(start: string, end: string) {
...
@@ -248,13 +388,14 @@ function calculateRowSpan(start: string, end: string) {
.schedule-item
{
.schedule-item
{
display
:
flex
;
display
:
flex
;
overflow
:
hidden
;
flex-direction
:
column
;
flex-direction
:
column
;
align-items
:
flex-start
;
/* Keeps text left-aligned */
align-items
:
flex-start
;
/* Keeps text left-aligned */
justify-content
:
flex-start
;
/* Aligns content to the top */
justify-content
:
flex-start
;
/* Aligns content to the top */
padding
:
4
px
;
padding
:
6
px
;
border-radius
:
6px
;
border-radius
:
6px
;
margin
:
2px
;
margin
:
2px
;
background-color
:
color-mix
(
in
srgb
,
rgba
(
var
(
--v-global-theme-primary
))
70%
,
white
3
0%
);
background-color
:
color-mix
(
in
srgb
,
rgba
(
var
(
--v-global-theme-primary
))
80%
,
white
2
0%
);
color
:
white
;
color
:
white
;
font-size
:
12px
;
font-size
:
12px
;
outline
:
1px
solid
rgba
(
var
(
--v-border-color
),
var
(
--v-border-opacity
));
outline
:
1px
solid
rgba
(
var
(
--v-border-color
),
var
(
--v-border-opacity
));
...
@@ -297,6 +438,46 @@ function calculateRowSpan(start: string, end: string) {
...
@@ -297,6 +438,46 @@ function calculateRowSpan(start: string, end: string) {
text-align
:
start
;
/* Aligns room to the right */
text-align
:
start
;
/* Aligns room to the right */
}
}
.fixed-table
{
border-collapse
:
collapse
;
inline-size
:
100%
;
table-layout
:
fixed
;
}
.fixed-table
thead
th
{
background-color
:
rgba
(
var
(
--v-global-theme-primary
));
color
:
white
;
font-weight
:
bold
;
text-align
:
center
;
}
.fixed-table
th
,
.fixed-table
td
{
padding
:
0
;
margin
:
0
;
}
.schedule-box
{
padding
:
6px
;
border-radius
:
8px
;
color
:
white
;
font-size
:
0.85rem
;
min-block-size
:
90px
;
}
/* Color themes for items */
.schedule-color-red
{
background-color
:
#6aa1fa
;
}
.schedule-color-blue
{
background-color
:
#46c298
;
}
.schedule-color-green
{
background-color
:
#eda36b
;
}
@media
screen
and
(
max-width
:
1200px
)
{
@media
screen
and
(
max-width
:
1200px
)
{
.course-title
{
.course-title
{
border-block-end
:
0
solid
;
border-block-end
:
0
solid
;
...
...
This diff is collapsed.
Click to expand it.
views/dstipro/beranda/UserProfileHeader.vue
View file @
ffdda07
...
@@ -183,6 +183,12 @@ const ulangTahunBerikutnya = computed(() => {
...
@@ -183,6 +183,12 @@ const ulangTahunBerikutnya = computed(() => {
const
goToParking
=
()
=>
{
const
goToParking
=
()
=>
{
window
.
open
(
'https://parkir.ui.ac.id/apps/site/index'
,
'_blank'
)
window
.
open
(
'https://parkir.ui.ac.id/apps/site/index'
,
'_blank'
)
}
}
const
dialog
=
ref
(
false
)
function
openDialog
()
{
dialog
.
value
=
true
}
</
script
>
</
script
>
<
template
>
<
template
>
...
@@ -249,7 +255,7 @@ const goToParking = () => {
...
@@ -249,7 +255,7 @@ const goToParking = () => {
<VBtn
<VBtn
variant=
"tonal"
variant=
"tonal"
:color=
"daysLeft > 0 ? 'primary' : 'error'"
:color=
"daysLeft > 0 ? 'primary' : 'error'"
@
click=
"
goToParkin
g"
@
click=
"
openDialo
g"
>
>
{{
parkirStatus
}}
{{
parkirStatus
}}
<VTooltip
<VTooltip
...
@@ -287,8 +293,65 @@ const goToParking = () => {
...
@@ -287,8 +293,65 @@ const goToParking = () => {
</div>
</div>
</VTooltip>
</VTooltip>
</VBtn>
</VBtn>
</div>
<!-- Dialog popup -->
<VDialog
v-model=
"dialog"
width=
"400"
>
<template
#
default
>
<VCard>
<VCardTitle>
Informasi Parkir
</VCardTitle>
<VCardText>
<div
class=
"d-flex align-center gap-x-2 mb-2"
>
<VIcon
size=
"20"
icon=
"ri-calendar-line"
/>
<span>
Mulai:
{{
parkirItems
.
date_start_service
}}
</span>
</div>
<div
class=
"d-flex align-center gap-x-2 mb-2"
>
<VIcon
size=
"20"
icon=
"ri-calendar-check-line"
/>
<span>
Berakhir:
{{
parkirItems
.
date_end_service
}}
</span>
</div>
<div
class=
"d-flex align-center gap-x-2 mb-4"
>
<VIcon
size=
"20"
icon=
"ri-time-line"
/>
<span>
{{
daysLeft
}}
hari tersisa
</span>
</div>
<VProgressLinear
:model-value=
"progress"
color=
"primary"
height=
"6"
rounded
/>
</VCardText>
<VCardActions>
<VSpacer
/>
<VBtn
color=
"primary"
@
click=
"goToParking"
>
Lihat Detail
</VBtn>
<VBtn
text
@
click=
"dialog = false"
>
Tutup
</VBtn>
</VCardActions>
</VCard>
</
template
>
</VDialog>
</div>
<div
<div
v-if=
"!isBirthday"
v-if=
"!isBirthday"
class=
"d-flex align-center gap-x-2"
class=
"d-flex align-center gap-x-2"
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment