Added fonts, and a lot of UI cleanup.
This commit is contained in:
		
							parent
							
								
									b69852817e
								
							
						
					
					
						commit
						117e7bf992
					
				| 
						 | 
				
			
			@ -18,15 +18,17 @@ async function logOut() {
 | 
			
		|||
    <div>
 | 
			
		||||
      <nav class="global-navbar">
 | 
			
		||||
        <div>
 | 
			
		||||
          <RouterLink to="/">Home</RouterLink>
 | 
			
		||||
          <span style="font-weight: bold; font-size: large;">Teacher Tools</span>
 | 
			
		||||
          <RouterLink to="/">Apps</RouterLink>
 | 
			
		||||
          <RouterLink to="/my-account" v-if="authStore.state">My Account</RouterLink>
 | 
			
		||||
          <RouterLink to="/admin-dashboard" v-if="authStore.admin">Admin</RouterLink>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div>
 | 
			
		||||
          <RouterLink to="/login" v-if="!authStore.state">Login</RouterLink>
 | 
			
		||||
          <span v-if="authStore.state" style="margin-right: 0.5em">
 | 
			
		||||
            Logged in as <span v-text="authStore.state.username" style="font-weight: bold;"></span>
 | 
			
		||||
          <span v-if="authStore.state" style="margin-right: 0.25em; font-style: italic; font-size: smaller;">
 | 
			
		||||
            Logged in as <span v-text="authStore.state.username"
 | 
			
		||||
              style="font-weight: bold; font-style: normal; font-size: medium;"></span>
 | 
			
		||||
          </span>
 | 
			
		||||
          <button type="button" @click="logOut" v-if="authStore.state">Log out</button>
 | 
			
		||||
        </div>
 | 
			
		||||
| 
						 | 
				
			
			@ -52,7 +54,17 @@ async function logOut() {
 | 
			
		|||
  display: inline-block;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.global-navbar>div>a+a {
 | 
			
		||||
  margin-left: 0.5em;
 | 
			
		||||
.global-navbar>div>*+* {
 | 
			
		||||
  margin-left: 1em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.global-navbar a {
 | 
			
		||||
  color: inherit;
 | 
			
		||||
  text-decoration: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.global-navbar a:hover {
 | 
			
		||||
  text-decoration: underline;
 | 
			
		||||
  color: lightgray;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,6 +24,8 @@ const router = useRouter()
 | 
			
		|||
  padding: 10px;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
  max-width: 500px;
 | 
			
		||||
  margin-left: auto;
 | 
			
		||||
  margin-right: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.class-item:hover {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -78,9 +78,9 @@ async function resetStudentDesks() {
 | 
			
		|||
</script>
 | 
			
		||||
<template>
 | 
			
		||||
  <div v-if="cls">
 | 
			
		||||
    <h1>Class <span v-text="cls.number"></span></h1>
 | 
			
		||||
    <p>School Year: <span v-text="cls.schoolYear"></span></p>
 | 
			
		||||
    <div class="button-bar" style="margin-bottom: 1em;">
 | 
			
		||||
    <h1 class="align-center" style="margin-bottom: 0;">Class <span v-text="cls.number"></span></h1>
 | 
			
		||||
    <p class="align-center" style="margin-top: 0; margin-bottom: 2em;">For the {{ cls.schoolYear }} school year.</p>
 | 
			
		||||
    <div class="button-bar align-center" style="margin-bottom: 1em;">
 | 
			
		||||
      <button type="button" @click="router.push(`/classroom-compliance/classes/${cls.id}/edit-student`)">Add
 | 
			
		||||
        Student</button>
 | 
			
		||||
      <button type="button" @click="router.push(`/classroom-compliance/classes/${cls.id}/import-students`)">Import
 | 
			
		||||
| 
						 | 
				
			
			@ -89,16 +89,18 @@ async function resetStudentDesks() {
 | 
			
		|||
      <button type="button" @click="deleteThisClass">Delete this Class</button>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <h3>Notes</h3>
 | 
			
		||||
    <form @submit.prevent="submitNote">
 | 
			
		||||
      <textarea style="min-height: 50px; min-width: 300px;" maxlength="2000" minlength="1"
 | 
			
		||||
        v-model="noteContent"></textarea>
 | 
			
		||||
      <button style="vertical-align: top; margin-left: 0.5em;" type="submit">Add Note</button>
 | 
			
		||||
    </form>
 | 
			
		||||
    <ClassNoteItem v-for="note in notes" :key="note.id" :note="note" @noteDeleted="refreshNotes()" />
 | 
			
		||||
 | 
			
		||||
    <EntriesTable :classId="cls.id" ref="entries-table" />
 | 
			
		||||
 | 
			
		||||
    <div>
 | 
			
		||||
      <h3 style="margin-bottom: 0.25em;">Notes</h3>
 | 
			
		||||
      <form @submit.prevent="submitNote">
 | 
			
		||||
        <textarea style="min-height: 50px; min-width: 300px;" maxlength="2000" minlength="1"
 | 
			
		||||
          v-model="noteContent"></textarea>
 | 
			
		||||
        <button style="vertical-align: top; margin-left: 0.5em;" type="submit">Add Note</button>
 | 
			
		||||
      </form>
 | 
			
		||||
      <ClassNoteItem v-for="note in notes" :key="note.id" :note="note" @noteDeleted="refreshNotes()" />
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <!-- Confirmation dialog used for attempts at deleting this class. -->
 | 
			
		||||
    <ConfirmDialog ref="deleteClassDialog">
 | 
			
		||||
      <p>
 | 
			
		||||
| 
						 | 
				
			
			@ -109,4 +111,3 @@ async function resetStudentDesks() {
 | 
			
		|||
    </ConfirmDialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<style scoped></style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,7 @@ const authStore = useAuthStore()
 | 
			
		|||
const router = useRouter()
 | 
			
		||||
const apiClient = new ClassroomComplianceAPIClient(authStore)
 | 
			
		||||
 | 
			
		||||
onMounted(async () => {
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  apiClient.getClasses().handleErrorsWithAlert().then(result => {
 | 
			
		||||
    if (result) classes.value = result
 | 
			
		||||
  })
 | 
			
		||||
| 
						 | 
				
			
			@ -19,7 +19,7 @@ onMounted(async () => {
 | 
			
		|||
</script>
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <div class="button-bar">
 | 
			
		||||
    <div class="button-bar align-center">
 | 
			
		||||
      <button type="button" @click="router.push('/classroom-compliance/edit-class')">Add Class</button>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,13 +54,16 @@ function resetForm() {
 | 
			
		|||
}
 | 
			
		||||
</script>
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <h2>
 | 
			
		||||
  <div class="centered-content">
 | 
			
		||||
    <h2 class="align-center">
 | 
			
		||||
      <span v-if="cls" v-text="'Edit Class ' + cls.id"></span>
 | 
			
		||||
      <span v-if="!cls">Add New Class</span>
 | 
			
		||||
    </h2>
 | 
			
		||||
 | 
			
		||||
    <form @submit.prevent="submitForm" @reset.prevent="resetForm">
 | 
			
		||||
      <p>
 | 
			
		||||
        Add a new class to your classroom compliance app.
 | 
			
		||||
      </p>
 | 
			
		||||
      <div>
 | 
			
		||||
        <label for="number-input">Number</label>
 | 
			
		||||
        <input id="number-input" type="number" v-model="formData.number" required />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -127,13 +127,13 @@ async function doMoveClass() {
 | 
			
		|||
}
 | 
			
		||||
</script>
 | 
			
		||||
<template>
 | 
			
		||||
  <div v-if="cls">
 | 
			
		||||
    <h2>
 | 
			
		||||
  <div v-if="cls" class="centered-content">
 | 
			
		||||
    <h2 class="align-center">
 | 
			
		||||
      <span v-if="student" v-text="'Edit ' + student.name"></span>
 | 
			
		||||
      <span v-if="!student">Add New Student</span>
 | 
			
		||||
    </h2>
 | 
			
		||||
 | 
			
		||||
    <p>In class <span v-text="cls.number + ', ' + cls.schoolYear"></span></p>
 | 
			
		||||
    <p class="align-center">In class <span v-text="cls.number + ', ' + cls.schoolYear"></span></p>
 | 
			
		||||
 | 
			
		||||
    <form @submit.prevent="submitForm" @reset.prevent="resetForm">
 | 
			
		||||
      <div>
 | 
			
		||||
| 
						 | 
				
			
			@ -151,8 +151,8 @@ async function doMoveClass() {
 | 
			
		|||
        </p>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div>
 | 
			
		||||
        <label for="removed-checkbox" style="display: inline">Removed</label>
 | 
			
		||||
        <input id="removed-checkbox" type="checkbox" v-model="formData.removed" />
 | 
			
		||||
        <label for="removed-checkbox" style="display: inline">Removed</label>
 | 
			
		||||
        <p class="form-input-hint">
 | 
			
		||||
          Check this if the student has been removed from the class.
 | 
			
		||||
        </p>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -252,7 +252,7 @@ defineExpose({
 | 
			
		|||
</script>
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <div class="button-bar">
 | 
			
		||||
    <div class="button-bar" style="text-align: left;">
 | 
			
		||||
      <button type="button" @click="showPreviousWeek" :disabled="selectedView === TableView.TODAY">Previous
 | 
			
		||||
        Week</button>
 | 
			
		||||
      <button type="button" @click="showThisWeek" :disabled="selectedView === TableView.TODAY">This Week</button>
 | 
			
		||||
| 
						 | 
				
			
			@ -289,7 +289,7 @@ defineExpose({
 | 
			
		|||
 | 
			
		||||
    <table class="entries-table" :class="{ 'entries-table-reduced-view': selectedView !== TableView.FULL }">
 | 
			
		||||
      <thead>
 | 
			
		||||
        <tr>
 | 
			
		||||
        <tr class="align-center">
 | 
			
		||||
          <th v-if="selectedView !== TableView.WHITEBOARD">#</th>
 | 
			
		||||
          <th>Student</th>
 | 
			
		||||
          <th v-if="assignedDesks">Desk</th>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,7 +15,7 @@ const sampleEntry: Ref<Entry | null> = ref({
 | 
			
		|||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="guide-page">
 | 
			
		||||
  <div class="align-left centered-content">
 | 
			
		||||
    <h2>Guide</h2>
 | 
			
		||||
    <p>
 | 
			
		||||
      This page provides a quick guide to using the <em>Classroom Compliance</em>
 | 
			
		||||
| 
						 | 
				
			
			@ -149,10 +149,3 @@ const sampleEntry: Ref<Entry | null> = ref({
 | 
			
		|||
    </ul>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<style scoped>
 | 
			
		||||
.guide-page {
 | 
			
		||||
  max-width: 50ch;
 | 
			
		||||
  margin-left: auto;
 | 
			
		||||
  margin-right: auto;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,8 +32,8 @@ async function doImport() {
 | 
			
		|||
}
 | 
			
		||||
</script>
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <h1>Import Students</h1>
 | 
			
		||||
  <div class="centered-content">
 | 
			
		||||
    <h1 class="align-center">Import Students</h1>
 | 
			
		||||
    <p>
 | 
			
		||||
      Import a large number of students to a class at once by pasting their names in the text box below, with one
 | 
			
		||||
      student per line.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ async function downloadExport() {
 | 
			
		|||
}
 | 
			
		||||
</script>
 | 
			
		||||
<template>
 | 
			
		||||
  <main>
 | 
			
		||||
  <main class="app-header">
 | 
			
		||||
    <h1>Classroom Compliance</h1>
 | 
			
		||||
 | 
			
		||||
    <div class="button-bar">
 | 
			
		||||
| 
						 | 
				
			
			@ -31,6 +31,8 @@ async function downloadExport() {
 | 
			
		|||
    </div>
 | 
			
		||||
    <hr />
 | 
			
		||||
 | 
			
		||||
    <RouterView :key="$route.fullPath" />
 | 
			
		||||
    <div class="align-left">
 | 
			
		||||
      <RouterView :key="$route.fullPath" />
 | 
			
		||||
    </div>
 | 
			
		||||
  </main>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
<script setup lang="ts">
 | 
			
		||||
import { ClassroomComplianceAPIClient, type Entry, type Student } from '@/api/classroom_compliance';
 | 
			
		||||
import { useAuthStore } from '@/stores/auth';
 | 
			
		||||
import { onMounted, ref, type Ref } from 'vue';
 | 
			
		||||
import StudentEntryItem from './StudentEntryItem.vue';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const props = defineProps<{
 | 
			
		||||
  student: Student
 | 
			
		||||
}>()
 | 
			
		||||
const authStore = useAuthStore()
 | 
			
		||||
 | 
			
		||||
const entries: Ref<Entry[]> = ref([])
 | 
			
		||||
 | 
			
		||||
const apiClient = new ClassroomComplianceAPIClient(authStore)
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  apiClient.getStudentEntries(props.student.classId, props.student.id).handleErrorsWithAlert()
 | 
			
		||||
    .then(result => {
 | 
			
		||||
      if (result !== null) {
 | 
			
		||||
        entries.value = result
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
})
 | 
			
		||||
</script>
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <h3 class="align-center">Entries</h3>
 | 
			
		||||
    <div>
 | 
			
		||||
      <StudentEntryItem v-for="entry in entries" :key="entry.id" :entry="entry" />
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			@ -1,13 +1,19 @@
 | 
			
		|||
<script setup lang="ts">
 | 
			
		||||
import { EMOJI_ABSENT, EMOJI_BEHAVIOR_GOOD, EMOJI_BEHAVIOR_MEDIOCRE, EMOJI_BEHAVIOR_POOR, EMOJI_PHONE_COMPLIANT, EMOJI_PHONE_NONCOMPLIANT, EMOJI_PRESENT, type Entry } from '@/api/classroom_compliance';
 | 
			
		||||
 | 
			
		||||
defineProps<{
 | 
			
		||||
const props = defineProps<{
 | 
			
		||||
  entry: Entry
 | 
			
		||||
}>()
 | 
			
		||||
 | 
			
		||||
function getFormattedDate() {
 | 
			
		||||
  const d = new Date(props.entry.date)
 | 
			
		||||
  const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
 | 
			
		||||
  return days[d.getDay()] + ', ' + d.toLocaleDateString()
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="student-entry-item">
 | 
			
		||||
    <h6>{{ entry.date }}</h6>
 | 
			
		||||
    <h6>{{ getFormattedDate() }}</h6>
 | 
			
		||||
    <div class="icons-container">
 | 
			
		||||
      <span v-if="entry.absent">{{ EMOJI_ABSENT }}</span>
 | 
			
		||||
      <span v-if="!entry.absent">{{ EMOJI_PRESENT }}</span>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,7 @@ import ConfirmDialog from '@/components/ConfirmDialog.vue'
 | 
			
		|||
import { useAuthStore } from '@/stores/auth'
 | 
			
		||||
import { onMounted, ref, useTemplateRef, type Ref } from 'vue'
 | 
			
		||||
import { useRouter } from 'vue-router'
 | 
			
		||||
import StudentEntryItem from '@/apps/classroom_compliance/StudentEntryItem.vue'
 | 
			
		||||
import StudentEntriesList from './StudentEntriesList.vue'
 | 
			
		||||
 | 
			
		||||
const props = defineProps<{
 | 
			
		||||
  classId: string
 | 
			
		||||
| 
						 | 
				
			
			@ -53,43 +53,51 @@ async function deleteThisStudent() {
 | 
			
		|||
}
 | 
			
		||||
</script>
 | 
			
		||||
<template>
 | 
			
		||||
  <div v-if="student">
 | 
			
		||||
    <h2 v-text="student.name"></h2>
 | 
			
		||||
    <p>
 | 
			
		||||
  <div v-if="student" class="centered-content">
 | 
			
		||||
    <h2 class="align-center" v-text="student.name"></h2>
 | 
			
		||||
    <p class="align-center">
 | 
			
		||||
      From
 | 
			
		||||
      <RouterLink :to="'/classroom-compliance/classes/' + classId">
 | 
			
		||||
        <span v-text="'class ' + cls?.number + ', ' + cls?.schoolYear"></span>
 | 
			
		||||
      </RouterLink>
 | 
			
		||||
    </p>
 | 
			
		||||
    <ul>
 | 
			
		||||
      <li>Internal ID: <span v-text="student.id"></span></li>
 | 
			
		||||
      <li>Removed: <span v-text="student.removed"></span></li>
 | 
			
		||||
      <li>Desk number: <span v-text="student.deskNumber"></span></li>
 | 
			
		||||
    </ul>
 | 
			
		||||
 | 
			
		||||
    <div class="button-bar">
 | 
			
		||||
    <div class="button-bar align-center">
 | 
			
		||||
      <button type="button"
 | 
			
		||||
        @click="router.push(`/classroom-compliance/classes/${student.classId}/edit-student?studentId=${student.id}`)">Edit</button>
 | 
			
		||||
      <button type="button" @click="deleteThisStudent">Delete</button>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div v-if="statistics">
 | 
			
		||||
      <h3>Statistics</h3>
 | 
			
		||||
      <ul>
 | 
			
		||||
        <li>Attendance Rate: {{ (statistics.attendanceRate * 100).toFixed(1) }}%</li>
 | 
			
		||||
        <li>Phone Compliance Rate: {{ (statistics.phoneComplianceRate * 100).toFixed(1) }}%</li>
 | 
			
		||||
        <li>Behavior Score: {{ (statistics.behaviorScore * 100).toFixed(1) }}%</li>
 | 
			
		||||
        <li>From a total of {{ statistics.entryCount }} entries</li>
 | 
			
		||||
      </ul>
 | 
			
		||||
    </div>
 | 
			
		||||
    <table class="student-properties-table">
 | 
			
		||||
      <tbody>
 | 
			
		||||
        <tr>
 | 
			
		||||
          <th>Desk Number</th>
 | 
			
		||||
          <td>{{ student.deskNumber }}</td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tr>
 | 
			
		||||
          <th>Removed</th>
 | 
			
		||||
          <td>{{ student.removed ? 'True' : 'False' }}</td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tr v-if="statistics">
 | 
			
		||||
          <th>Attendance Rate</th>
 | 
			
		||||
          <td>{{ (statistics.attendanceRate * 100).toFixed(1) }}%</td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tr v-if="statistics">
 | 
			
		||||
          <th>Phone Compliance Rate</th>
 | 
			
		||||
          <td>{{ (statistics.phoneComplianceRate * 100).toFixed(1) }}%</td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tr v-if="statistics">
 | 
			
		||||
          <th>Behavior Score</th>
 | 
			
		||||
          <td>{{ (statistics.behaviorScore * 100).toFixed(1) }}%</td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tr v-if="statistics">
 | 
			
		||||
          <th>Total Entries</th>
 | 
			
		||||
          <td>{{ statistics.entryCount }}</td>
 | 
			
		||||
        </tr>
 | 
			
		||||
      </tbody>
 | 
			
		||||
    </table>
 | 
			
		||||
 | 
			
		||||
    <h3>Entries</h3>
 | 
			
		||||
    <p>
 | 
			
		||||
      Below is a record of all entries saved for <span>{{ student.name }}</span>.
 | 
			
		||||
    </p>
 | 
			
		||||
    <div>
 | 
			
		||||
      <StudentEntryItem v-for="entry in entries" :key="entry.id" :entry="entry" />
 | 
			
		||||
    </div>
 | 
			
		||||
    <StudentEntriesList :student="student" />
 | 
			
		||||
 | 
			
		||||
    <ConfirmDialog ref="deleteConfirmDialog">
 | 
			
		||||
      <p>
 | 
			
		||||
| 
						 | 
				
			
			@ -100,3 +108,18 @@ async function deleteThisStudent() {
 | 
			
		|||
    </ConfirmDialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<style scoped>
 | 
			
		||||
.student-properties-table {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  border-collapse: collapse;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.student-properties-table :is(th, td) {
 | 
			
		||||
  border: 1px solid gray;
 | 
			
		||||
  padding: 0.25em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.student-properties-table td {
 | 
			
		||||
  text-align: right;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,9 +5,9 @@ defineProps<{
 | 
			
		|||
</script>
 | 
			
		||||
<template>
 | 
			
		||||
  <td style="text-align: right; padding-right: 0.25em;">
 | 
			
		||||
    <span v-if="score !== null" style="font-family: monospace; font-size: large;">
 | 
			
		||||
    <span v-if="score !== null" class="text-mono">
 | 
			
		||||
      {{ (score * 100).toFixed(1) }}%
 | 
			
		||||
    </span>
 | 
			
		||||
    <span v-if="score === null" style="font-size: small; font-style: italic;">No score</span>
 | 
			
		||||
    <span v-if="score === null" style="font-style: italic; color: gray;">No score</span>
 | 
			
		||||
  </td>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,28 @@
 | 
			
		|||
@font-face {
 | 
			
		||||
  font-family: 'Open Sans';
 | 
			
		||||
  src: url('@/assets/fonts/OpenSans.ttf');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@font-face {
 | 
			
		||||
  font-family: 'Open Sans';
 | 
			
		||||
  src: url('@/assets/fonts/OpenSans-Italic.ttf');
 | 
			
		||||
  font-style: italic;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@font-face {
 | 
			
		||||
  font-family: 'SourceCodePro';
 | 
			
		||||
  src: url('@/assets/fonts/SourceCodePro.ttf');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@font-face {
 | 
			
		||||
  font-family: 'SourceCodePro';
 | 
			
		||||
  src: url('@/assets/fonts/SourceCodePro-Italic.ttf');
 | 
			
		||||
  font-style: italic;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
:root {
 | 
			
		||||
  color-scheme: light dark;
 | 
			
		||||
  font-family: sans-serif;
 | 
			
		||||
  font-family: 'Open Sans', sans-serif;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.button-bar {
 | 
			
		||||
| 
						 | 
				
			
			@ -12,10 +34,46 @@
 | 
			
		|||
  margin-left: 0.5em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.align-left {
 | 
			
		||||
  text-align: left;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.align-right {
 | 
			
		||||
  text-align: right;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.align-center {
 | 
			
		||||
  text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.centered-content {
 | 
			
		||||
  max-width: 50ch;
 | 
			
		||||
  margin-left: auto;
 | 
			
		||||
  margin-right: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
code {
 | 
			
		||||
  font-family: 'SourceCodePro', monospace;
 | 
			
		||||
  color: lime;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.text-mono {
 | 
			
		||||
  font-family: 'SourceCodePro', monospace;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
label {
 | 
			
		||||
  display: block;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
textarea {
 | 
			
		||||
  font-family: 'SourceCodePro', monospace;
 | 
			
		||||
  font-size: smaller;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
button {
 | 
			
		||||
  font-family: 'Open Sans', sans-serif;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
form > div + div {
 | 
			
		||||
  margin-top: 0.5em;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -25,3 +83,10 @@ form > div + div {
 | 
			
		|||
  font-style: italic;
 | 
			
		||||
  margin-top: 0.25em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.app-header {
 | 
			
		||||
  text-align: center;
 | 
			
		||||
}
 | 
			
		||||
.app-header > h1 {
 | 
			
		||||
  margin-bottom: 0.5em;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
<script setup lang="ts">
 | 
			
		||||
defineProps<{
 | 
			
		||||
  name: string,
 | 
			
		||||
  route: string
 | 
			
		||||
}>()
 | 
			
		||||
</script>
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-list-item">
 | 
			
		||||
    <h3>
 | 
			
		||||
      <RouterLink :to="route">{{ name }}</RouterLink>
 | 
			
		||||
    </h3>
 | 
			
		||||
    <p>
 | 
			
		||||
      <slot></slot>
 | 
			
		||||
    </p>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<style scoped>
 | 
			
		||||
.app-list-item {
 | 
			
		||||
  padding: 1em;
 | 
			
		||||
  background-color: rgb(49, 49, 49);
 | 
			
		||||
  border-radius: 20px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.app-list-item>h3 {
 | 
			
		||||
  margin-top: 0;
 | 
			
		||||
  margin-bottom: 0;
 | 
			
		||||
  font-size: x-large;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.app-list-item>h3>a {
 | 
			
		||||
  text-decoration: none;
 | 
			
		||||
  color: inherit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.app-list-item>h3>a:hover {
 | 
			
		||||
  text-decoration: underline;
 | 
			
		||||
  color: lightgray;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			@ -36,20 +36,10 @@ defineExpose({
 | 
			
		|||
    <form>
 | 
			
		||||
      <slot></slot>
 | 
			
		||||
 | 
			
		||||
      <div class="confirm-dialog-buttons">
 | 
			
		||||
      <div class="button-bar align-right">
 | 
			
		||||
        <button @click.prevent="onConfirmClicked">Confirm</button>
 | 
			
		||||
        <button @click.prevent="onCancelClicked">Cancel</button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </form>
 | 
			
		||||
  </dialog>
 | 
			
		||||
</template>
 | 
			
		||||
<style>
 | 
			
		||||
.confirm-dialog-buttons {
 | 
			
		||||
  text-align: right;
 | 
			
		||||
  margin-top: 0.5em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.confirm-dialog-buttons>button {
 | 
			
		||||
  margin-left: 0.5em;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,25 +1,18 @@
 | 
			
		|||
<script setup lang="ts"></script>
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import AppListItem from '@/components/AppListItem.vue';
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <main>
 | 
			
		||||
    <h1>Home Page</h1>
 | 
			
		||||
    <p>
 | 
			
		||||
      Welcome to Teacher-Tools, a website with tools that help teachers to manage their classrooms.
 | 
			
		||||
  <main class="centered-content">
 | 
			
		||||
    <h1 class="align-center">My Applications</h1>
 | 
			
		||||
 | 
			
		||||
    <AppListItem name="Classroom Compliance" route="/classroom-compliance">
 | 
			
		||||
      Track your students' phone usage and behavior, record notes, and automatically calculate weekly scores for each
 | 
			
		||||
      student.
 | 
			
		||||
    </AppListItem>
 | 
			
		||||
    <p style="text-align: right; font-style: italic;">
 | 
			
		||||
      ... and more apps coming soon!
 | 
			
		||||
    </p>
 | 
			
		||||
    <hr>
 | 
			
		||||
    <h2>Applications</h2>
 | 
			
		||||
    <p>
 | 
			
		||||
      The following list of applications are available for you:
 | 
			
		||||
    </p>
 | 
			
		||||
    <ul>
 | 
			
		||||
      <li>
 | 
			
		||||
        <RouterLink to="/classroom-compliance">Classroom Compliance</RouterLink>
 | 
			
		||||
        -
 | 
			
		||||
        Track your students' phone usage and behavior patterns, and calculate weighted grades.
 | 
			
		||||
      </li>
 | 
			
		||||
      <li>
 | 
			
		||||
        <em>... and more to come soon!</em>
 | 
			
		||||
      </li>
 | 
			
		||||
    </ul>
 | 
			
		||||
  </main>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,9 +4,9 @@ import { useAuthStore } from '@/stores/auth';
 | 
			
		|||
const authStore = useAuthStore()
 | 
			
		||||
</script>
 | 
			
		||||
<template>
 | 
			
		||||
  <main v-if="authStore.state">
 | 
			
		||||
    <h1>My Account</h1>
 | 
			
		||||
    <table>
 | 
			
		||||
  <main v-if="authStore.state" class="centered-content">
 | 
			
		||||
    <h1 class="align-center">My Account</h1>
 | 
			
		||||
    <table class="account-properties-table">
 | 
			
		||||
      <tbody>
 | 
			
		||||
        <tr>
 | 
			
		||||
          <th>Internal ID</th>
 | 
			
		||||
| 
						 | 
				
			
			@ -33,5 +33,30 @@ const authStore = useAuthStore()
 | 
			
		|||
    <p>
 | 
			
		||||
      Please contact Andrew Lalis for help with account administration or to report any bugs you find!
 | 
			
		||||
    </p>
 | 
			
		||||
    <p>
 | 
			
		||||
      Suggestions for new features are also highly encouraged!
 | 
			
		||||
    </p>
 | 
			
		||||
    <p>
 | 
			
		||||
      Contact Andrew at <a href="https://www.andrewlalis.com/contact" target="_blank">andrewlalis.com/contact</a>.
 | 
			
		||||
    </p>
 | 
			
		||||
  </main>
 | 
			
		||||
</template>
 | 
			
		||||
<style scoped>
 | 
			
		||||
.account-properties-table {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  border-collapse: collapse;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.account-properties-table :is(th, td) {
 | 
			
		||||
  border: 1px solid gray;
 | 
			
		||||
  padding: 0.25em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.account-properties-table th {
 | 
			
		||||
  text-align: left;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.account-properties-table td {
 | 
			
		||||
  text-align: right;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue