Compare commits

...
3 Commits
8 changed files with 1656 additions and 3 deletions
+1
View File
@@ -0,0 +1 @@
registry=https://registry.npmmirror.com/
+3 -3
View File
@@ -3,9 +3,9 @@ FROM node:22-alpine
WORKDIR /app WORKDIR /app
# Copy package descriptors and install dependencies # Copy package descriptors and npm configuration
COPY package*.json ./ COPY package*.json .npmrc* ./
RUN npm ci RUN npm ci --registry=https://registry.npmmirror.com
# Copy application source code # Copy application source code
COPY . . COPY . .
+6
View File
@@ -0,0 +1,6 @@
// /src/api/professorApi.js
import axiosInstance from './axiosInstance'
export const professorApi = {
getPortal: () => axiosInstance.get('/professors/portal')
}
+24
View File
@@ -12,6 +12,10 @@
</div> </div>
<nav> <nav>
<RouterLink :to="{ name: 'account' }" class="nav-link">خلاصه</RouterLink> <RouterLink :to="{ name: 'account' }" class="nav-link">خلاصه</RouterLink>
<RouterLink v-if="auth.isProfessor" :to="{ name: 'professor-portal' }" class="nav-link professor-link">
<span class="professor-icon">🎓</span>
میزکار تدریس و اساتید
</RouterLink>
<RouterLink :to="{ name: 'my-classes' }" class="nav-link">کلاسهای من</RouterLink> <RouterLink :to="{ name: 'my-classes' }" class="nav-link">کلاسهای من</RouterLink>
<RouterLink :to="{ name: 'my-certificates' }" class="nav-link">گواهینامهها</RouterLink> <RouterLink :to="{ name: 'my-certificates' }" class="nav-link">گواهینامهها</RouterLink>
</nav> </nav>
@@ -121,6 +125,26 @@ nav {
color: var(--leaf); color: var(--leaf);
} }
.professor-link {
display: flex;
align-items: center;
gap: 0.5rem;
background: rgba(232, 163, 23, 0.08);
border: 1px solid rgba(232, 163, 23, 0.25);
color: var(--ink);
}
.professor-link:hover,
.professor-link.router-link-active {
background: linear-gradient(135deg, rgba(232, 163, 23, 0.2), rgba(45, 106, 79, 0.15));
color: var(--ink);
border-color: var(--saffron);
}
.professor-icon {
font-size: 1.1rem;
}
.logout-btn { .logout-btn {
margin-top: 1.25rem; margin-top: 1.25rem;
width: 100%; width: 100%;
+6
View File
@@ -43,6 +43,12 @@ const routes = [
component: () => import('@/views/account/AccountHomeView.vue'), component: () => import('@/views/account/AccountHomeView.vue'),
meta: { title: 'پنل کاربری | گام نو' } meta: { title: 'پنل کاربری | گام نو' }
}, },
{
path: 'teaching',
name: 'professor-portal',
component: () => import('@/views/account/ProfessorPortalView.vue'),
meta: { title: 'میزکار اساتید و تدریس | گام نو' }
},
{ {
path: 'classes', path: 'classes',
name: 'my-classes', name: 'my-classes',
+5
View File
@@ -13,6 +13,10 @@ export const useAuthStore = defineStore('auth', () => {
if (!user.value) return '' if (!user.value) return ''
return `${user.value.name || ''}`.trim() return `${user.value.name || ''}`.trim()
}) })
const isProfessor = computed(() => {
const roleName = user.value?.role?.name || user.value?.role
return roleName === 'Professor' || user.value?.isProfessor === true
})
function setTokens(access, refresh) { function setTokens(access, refresh) {
accessToken.value = access accessToken.value = access
@@ -71,6 +75,7 @@ export const useAuthStore = defineStore('auth', () => {
user, user,
isAuthenticated, isAuthenticated,
fullName, fullName,
isProfessor,
setTokens, setTokens,
setUser, setUser,
login, login,
+82
View File
@@ -5,6 +5,17 @@
<p>کلاسهای ثبتشده و گواهینامههایتان را از اینجا مدیریت کنید.</p> <p>کلاسهای ثبتشده و گواهینامههایتان را از اینجا مدیریت کنید.</p>
</header> </header>
<div v-if="auth.isProfessor" class="professor-banner">
<div class="professor-banner-content">
<div class="professor-badge-pill">🎓 پنل ویژه اساتید گام نو</div>
<h2>میزکار و پنل تدریس اساتید</h2>
<p>مشاهده کلاسهای در حال برگزاری، زمانبندی جلسات، آمار دانشجویان و گزارش و نمودار سهم تدریس شما</p>
</div>
<RouterLink :to="{ name: 'professor-portal' }" class="professor-cta-btn">
ورود به میزکار تدریس
</RouterLink>
</div>
<div class="summary-grid"> <div class="summary-grid">
<RouterLink :to="{ name: 'my-classes' }" class="summary-tile"> <RouterLink :to="{ name: 'my-classes' }" class="summary-tile">
<span class="tile-label">کلاسهای من</span> <span class="tile-label">کلاسهای من</span>
@@ -72,6 +83,77 @@ onMounted(async () => {
color: var(--ink-soft); color: var(--ink-soft);
} }
.professor-banner {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1.5rem;
padding: 1.5rem 1.75rem;
margin-bottom: 1.5rem;
border-radius: 1.25rem;
background: linear-gradient(135deg, #14352b 0%, #1f4e3f 60%, #2d6a4f 100%);
color: var(--chalk);
box-shadow: 0 10px 25px -5px rgba(20, 53, 43, 0.25);
border: 1px solid rgba(232, 163, 23, 0.3);
}
.professor-badge-pill {
display: inline-block;
font-size: 0.75rem;
font-weight: 700;
padding: 0.2rem 0.65rem;
border-radius: 999px;
background: rgba(232, 163, 23, 0.2);
color: #ffd166;
border: 1px solid rgba(232, 163, 23, 0.4);
margin-bottom: 0.5rem;
}
.professor-banner h2 {
font-family: var(--font-display);
font-size: 1.35rem;
color: #fff;
margin: 0 0 0.35rem 0;
}
.professor-banner p {
font-size: 0.88rem;
color: rgba(255, 255, 255, 0.85);
margin: 0;
line-height: 1.5;
max-width: 540px;
}
.professor-cta-btn {
white-space: nowrap;
padding: 0.75rem 1.25rem;
border-radius: 0.85rem;
background: var(--saffron);
color: var(--ink);
font-weight: 700;
font-size: 0.9rem;
box-shadow: 0 4px 12px rgba(232, 163, 23, 0.3);
transition: transform 0.2s ease, box-shadow 0.2s ease;
flex-shrink: 0;
}
.professor-cta-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 16px rgba(232, 163, 23, 0.4);
}
@media (max-width: 768px) {
.professor-banner {
flex-direction: column;
align-items: flex-start;
padding: 1.25rem;
}
.professor-cta-btn {
width: 100%;
text-align: center;
}
}
.summary-grid { .summary-grid {
display: grid; display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: repeat(2, minmax(0, 1fr));
File diff suppressed because it is too large Load Diff