Skip to content

Commit

Permalink
assigned employee
Browse files Browse the repository at this point in the history
  • Loading branch information
Joosakur committed Nov 29, 2023
1 parent 77e2814 commit 6467331
Show file tree
Hide file tree
Showing 17 changed files with 206 additions and 101 deletions.
2 changes: 1 addition & 1 deletion frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ function App() {
<UserContextProvider user={user}>
<div>
<Header>
<H1>Espoon kaupunki - Oppivelvollisuuden valvonta</H1>
<H1>Espoon kaupunki - Oppivelvollisuuden seuranta</H1>
<UserHeader />
</Header>
<AppContainer>
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/api-client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import axios from 'axios'

export const apiClient = axios.create({
baseURL: '/api'
baseURL: '/api',
xsrfCookieName: 'oppivelvollisuus.xsrf'
})
6 changes: 3 additions & 3 deletions frontend/src/auth/UserContext.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, { createContext, useMemo } from 'react'

import { User } from './auth-status'
import { EmployeeUser } from '../employees/api'

export interface UserState {
user: User | null
user: EmployeeUser | null
}

export const UserContext = createContext<UserState>({
Expand All @@ -15,7 +15,7 @@ export const UserContextProvider = React.memo(function UserContextProvider({
user
}: {
children: React.JSX.Element
user: User | null
user: EmployeeUser | null
}) {
const value = useMemo(
() => ({
Expand Down
10 changes: 2 additions & 8 deletions frontend/src/auth/auth-status.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import { useEffect, useState } from 'react'

import { apiClient } from '../api-client'
import { EmployeeUser } from '../employees/api'
import { JsonOf } from '../shared/api-utils'

export interface User {
externalId: string
firstName: string
lastName: string
email?: string | null
}

export interface AuthStatus {
loggedIn: boolean
user?: User
user?: EmployeeUser
apiVersion: string
}

Expand Down
17 changes: 17 additions & 0 deletions frontend/src/employees/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { apiClient } from '../api-client'
import { JsonOf } from '../shared/api-utils'

export interface EmployeeUser {
externalId: string
firstName: string
lastName: string
email?: string | null
}

export interface EmployeeBasics {
id: string
name: string
}

export const apiGetEmployees = (): Promise<EmployeeUser[]> =>
apiClient.get<JsonOf<EmployeeUser[]>>('/employees').then((res) => res.data)
12 changes: 10 additions & 2 deletions frontend/src/students/CreateStudentPage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useState } from 'react'
import React, { useEffect, useState } from 'react'
import { Link, useNavigate } from 'react-router-dom'

import { apiGetEmployees, EmployeeUser } from '../employees/api'
import { VerticalGap } from '../shared/layout'
import { H2, H3 } from '../shared/typography'

Expand All @@ -11,11 +12,18 @@ import { apiPostStudent, StudentCaseInput, StudentInput } from './api'
export const CreateStudentPage = React.memo(function CreateStudentPage() {
const navigate = useNavigate()

const [employees, setEmployees] = useState<EmployeeUser[] | null>(null)
useEffect(() => {
void apiGetEmployees().then(setEmployees)
}, [])

const [studentInput, setStudentInput] = useState<StudentInput | null>(null)
const [studentCaseInput, setStudentCaseInput] =
useState<StudentCaseInput | null>(null)
const [submitting, setSubmitting] = useState(false)

if (!employees) return <div>...</div>

return (
<div>
<Link to="/oppivelvolliset">Takaisin</Link>
Expand All @@ -31,7 +39,7 @@ export const CreateStudentPage = React.memo(function CreateStudentPage() {
<VerticalGap $size="m" />
<H3>Ilmoituksen tiedot</H3>
<VerticalGap $size="m" />
<StudentCaseForm onChange={setStudentCaseInput} />
<StudentCaseForm onChange={setStudentCaseInput} employees={employees} />
<VerticalGap $size="m" />

<button
Expand Down
57 changes: 42 additions & 15 deletions frontend/src/students/StudentCaseForm.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import React, { useEffect, useMemo, useState } from 'react'

import { EmployeeUser } from '../employees/api'
import { formatDate, parseDate } from '../shared/dates'
import { FlexColWithGaps } from '../shared/layout'
import { FlexColWithGaps, FlexRowWithGaps } from '../shared/layout'
import { Label, P } from '../shared/typography'

import { StudentCase, StudentCaseInput } from './api'

interface CreateProps {
onChange: (validInput: StudentCaseInput | null) => void
employees: EmployeeUser[]
}
interface ViewProps {
studentCase: StudentCase
Expand All @@ -17,6 +19,7 @@ interface EditProps {
studentCase: StudentCase
editing: true
onChange: (validInput: StudentCaseInput | null) => void
employees: EmployeeUser[]
}
type Props = CreateProps | ViewProps | EditProps

Expand All @@ -37,6 +40,9 @@ export const StudentCaseForm = React.memo(function StudentCaseForm(
const [info, setInfo] = useState(
isCreating(props) ? '' : props.studentCase.info
)
const [assignedTo, setAssignedTo] = useState(
isCreating(props) ? null : props.studentCase.assignedTo?.id ?? null
)

const validInput: StudentCaseInput | null = useMemo(() => {
const openedAtDate = parseDate(openedAt.trim())
Expand All @@ -45,9 +51,10 @@ export const StudentCaseForm = React.memo(function StudentCaseForm(

return {
openedAt: openedAtDate,
info
info,
assignedTo
}
}, [openedAt, info])
}, [openedAt, info, assignedTo])

useEffect(() => {
if (!isViewing(props)) {
Expand All @@ -57,18 +64,38 @@ export const StudentCaseForm = React.memo(function StudentCaseForm(

return (
<FlexColWithGaps $gapSize="m">
<FlexColWithGaps>
<Label>Tapaus vastaanotettu</Label>
{isViewing(props) ? (
<span>{formatDate(props.studentCase.openedAt)}</span>
) : (
<input
type="text"
onChange={(e) => setOpenedAt(e.target.value)}
value={openedAt}
/>
)}
</FlexColWithGaps>
<FlexRowWithGaps $gapSize="L">
<FlexColWithGaps>
<Label>Tapaus vastaanotettu</Label>
{isViewing(props) ? (
<span>{formatDate(props.studentCase.openedAt)}</span>
) : (
<input
type="text"
onChange={(e) => setOpenedAt(e.target.value)}
value={openedAt}
/>
)}
</FlexColWithGaps>
<FlexColWithGaps>
<Label>Ohjaaja</Label>
{isViewing(props) ? (
<span>{props.studentCase.assignedTo?.name ?? '-'}</span>
) : (
<select
onChange={(e) => setAssignedTo(e.target.value || null)}
value={assignedTo ?? undefined}
>
<option value="">-</option>
{props.employees.map((e) => (
<option key={e.externalId} value={e.externalId}>
{e.firstName} {e.lastName}
</option>
))}
</select>
)}
</FlexColWithGaps>
</FlexRowWithGaps>
<FlexColWithGaps>
<Label>Tapauksen tiedot</Label>
{isViewing(props) ? (
Expand Down
14 changes: 12 additions & 2 deletions frontend/src/students/StudentPage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useCallback, useEffect, useState } from 'react'
import { Link, useParams } from 'react-router-dom'

import { apiGetEmployees, EmployeeUser } from '../employees/api'
import { formatDate } from '../shared/dates'
import {
FlexColWithGaps,
Expand All @@ -26,6 +27,11 @@ export const StudentPage = React.memo(function StudentPage() {
const { id } = useParams()
if (!id) throw Error('Id not found in path')

const [employees, setEmployees] = useState<EmployeeUser[] | null>(null)
useEffect(() => {
void apiGetEmployees().then(setEmployees)
}, [])

const [studentResponse, setStudentResponse] =
useState<StudentResponse | null>(null)
const loadStudent = useCallback(() => {
Expand Down Expand Up @@ -56,7 +62,7 @@ export const StudentPage = React.memo(function StudentPage() {

<VerticalGap $size="L" />

{studentResponse && (
{studentResponse && employees && (
<div>
<H3>Oppivelvollisen tiedot</H3>
<VerticalGap $size="m" />
Expand Down Expand Up @@ -117,7 +123,10 @@ export const StudentPage = React.memo(function StudentPage() {
{editingCase === true && (
<FlexColWithGaps>
<H3>Uusi ilmoitus</H3>
<StudentCaseForm onChange={setStudentCaseInput} />
<StudentCaseForm
onChange={setStudentCaseInput}
employees={employees}
/>
<FlexRowWithGaps>
<button
disabled={submitting || !studentCaseInput}
Expand Down Expand Up @@ -168,6 +177,7 @@ export const StudentPage = React.memo(function StudentPage() {
studentCase={studentCase}
editing={editingCase === studentCase.id}
onChange={setStudentCaseInput}
employees={employees}
/>
{editingCase === studentCase.id && (
<FlexRowWithGaps>
Expand Down
32 changes: 19 additions & 13 deletions frontend/src/students/StudentsSearchPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,26 @@ export const StudentsSearchPage = React.memo(function StudentsSearchPage() {

{studentsResponse && (
<Table>
<tr>
<th>Nimi</th>
<th>Ilmoitettu</th>
</tr>
{studentsResponse.map((student) => (
<tr key={student.id}>
<td>
<Link to={`/oppivelvolliset/${student.id}`}>
{student.lastName} {student.firstName}
</Link>
</td>
<td>{student.openedAt ? formatDate(student.openedAt) : '-'}</td>
<thead>
<tr>
<th>Nimi</th>
<th>Ilmoitettu</th>
<th>Ohjaaja</th>
</tr>
))}
</thead>
<tbody>
{studentsResponse.map((student) => (
<tr key={student.id}>
<td>
<Link to={`/oppivelvolliset/${student.id}`}>
{student.firstName} {student.lastName}
</Link>
</td>
<td>{student.openedAt ? formatDate(student.openedAt) : '-'}</td>
<td>{student.assignedTo?.name ?? ''}</td>
</tr>
))}
</tbody>
</Table>
)}
</div>
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/students/api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { formatISO, parseISO } from 'date-fns'

import { apiClient } from '../api-client'
import { EmployeeBasics } from '../employees/api'
import { JsonOf } from '../shared/api-utils'

export interface StudentInput {
Expand Down Expand Up @@ -54,6 +55,7 @@ export interface StudentSummary {
firstName: string
lastName: string
openedAt: Date | null
assignedTo: EmployeeBasics | null
}

export const apiGetStudents = (): Promise<StudentSummary[]> =>
Expand Down Expand Up @@ -99,11 +101,13 @@ export const apiGetStudent = (id: string): Promise<StudentResponse> =>
export interface StudentCaseInput {
openedAt: Date
info: string
assignedTo: string | null
}

export interface StudentCase extends StudentCaseInput {
export interface StudentCase extends Omit<StudentCaseInput, 'assignedTo'> {
id: string
studentId: string
assignedTo: EmployeeBasics | null
}

export const apiPostStudentCase = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,9 @@ class AppController {
tx.updateStudentCase(id = id, studentId = studentId, data = body)
}
}

@GetMapping("/employees")
fun getEmployees(): List<EmployeeUser> {
return jdbi.inTransactionUnchecked { it.getEmployees() }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ class DevDataInserter(jdbi: Jdbi) {
tx.createUpdate(
"""
INSERT INTO employees (external_id, first_name, last_name)
VALUES ('12345678-0000-0000-0000-000000000000', 'Sanna', 'Suunnittelija')
VALUES ('12345678-0000-0000-0000-000000000000', 'Sanna', 'Suunnittelija');
INSERT INTO employees (external_id, first_name, last_name)
VALUES ('12345678-0000-0000-0000-000000000001', 'Olli', 'Ohjaaja');
"""
).execute()
}
Expand Down
Loading

0 comments on commit 6467331

Please sign in to comment.