Compare commits
3 Commits
704f11cec3
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
668397104a
|
|||
|
0446e8f8a7
|
|||
|
975225e650
|
@@ -36,7 +36,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
working-directory: web
|
working-directory: web
|
||||||
run: npm install
|
run: npm install && npm exec -- allow-scripts
|
||||||
|
|
||||||
- name: Type check
|
- name: Type check
|
||||||
working-directory: web
|
working-directory: web
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# Stage 1: Build React frontend
|
# Stage 1: Build React frontend
|
||||||
FROM node:22-alpine AS frontend
|
FROM node:22-alpine AS frontend
|
||||||
WORKDIR /app/web
|
WORKDIR /app/web
|
||||||
COPY web/package*.json ./
|
COPY web/package*.json web/.npmrc ./
|
||||||
RUN npm install
|
RUN npm install && npm exec -- allow-scripts
|
||||||
COPY web/ ./
|
COPY web/ ./
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ tasks:
|
|||||||
web:install:
|
web:install:
|
||||||
desc: Install frontend dependencies
|
desc: Install frontend dependencies
|
||||||
dir: "{{.WEB_DIR}}"
|
dir: "{{.WEB_DIR}}"
|
||||||
cmd: npm install
|
cmds:
|
||||||
|
- npm install
|
||||||
|
- npm exec -- allow-scripts
|
||||||
sources:
|
sources:
|
||||||
- package.json
|
- package.json
|
||||||
generates:
|
generates:
|
||||||
|
|||||||
@@ -80,25 +80,20 @@ func (s *Store) Create(ctx context.Context, volunteerID int64, in CreateInput) (
|
|||||||
|
|
||||||
func (s *Store) GetByID(ctx context.Context, id int64) (*Request, error) {
|
func (s *Store) GetByID(ctx context.Context, id int64) (*Request, error) {
|
||||||
req := &Request{}
|
req := &Request{}
|
||||||
var startsAt, endsAt, createdAt, updatedAt string
|
|
||||||
var reason sql.NullString
|
var reason sql.NullString
|
||||||
var reviewedBy sql.NullInt64
|
var reviewedBy sql.NullInt64
|
||||||
var reviewedAt sql.NullString
|
var reviewedAt sql.NullTime
|
||||||
|
|
||||||
err := s.db.QueryRowContext(ctx,
|
err := s.db.QueryRowContext(ctx,
|
||||||
`SELECT id, volunteer_id, starts_at, ends_at, reason, status, reviewed_by, reviewed_at, created_at, updated_at
|
`SELECT id, volunteer_id, starts_at, ends_at, reason, status, reviewed_by, reviewed_at, created_at, updated_at
|
||||||
FROM time_off_requests WHERE id = ?`, id,
|
FROM time_off_requests WHERE id = ?`, id,
|
||||||
).Scan(&req.ID, &req.VolunteerID, &startsAt, &endsAt, &reason, &req.Status, &reviewedBy, &reviewedAt, &createdAt, &updatedAt)
|
).Scan(&req.ID, &req.VolunteerID, &req.StartsAt, &req.EndsAt, &reason, &req.Status, &reviewedBy, &reviewedAt, &req.CreatedAt, &req.UpdatedAt)
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
return nil, ErrNotFound
|
return nil, ErrNotFound
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("get time off request: %w", err)
|
return nil, fmt.Errorf("get time off request: %w", err)
|
||||||
}
|
}
|
||||||
req.StartsAt, _ = time.Parse("2006-01-02 15:04:05", startsAt)
|
|
||||||
req.EndsAt, _ = time.Parse("2006-01-02 15:04:05", endsAt)
|
|
||||||
req.CreatedAt, _ = time.Parse("2006-01-02 15:04:05", createdAt)
|
|
||||||
req.UpdatedAt, _ = time.Parse("2006-01-02 15:04:05", updatedAt)
|
|
||||||
if reason.Valid {
|
if reason.Valid {
|
||||||
req.Reason = reason.String
|
req.Reason = reason.String
|
||||||
}
|
}
|
||||||
@@ -106,8 +101,7 @@ func (s *Store) GetByID(ctx context.Context, id int64) (*Request, error) {
|
|||||||
req.ReviewedBy = &reviewedBy.Int64
|
req.ReviewedBy = &reviewedBy.Int64
|
||||||
}
|
}
|
||||||
if reviewedAt.Valid {
|
if reviewedAt.Valid {
|
||||||
t, _ := time.Parse("2006-01-02 15:04:05", reviewedAt.String)
|
req.ReviewedAt = &reviewedAt.Time
|
||||||
req.ReviewedAt = &t
|
|
||||||
}
|
}
|
||||||
return req, nil
|
return req, nil
|
||||||
}
|
}
|
||||||
@@ -130,17 +124,12 @@ func (s *Store) List(ctx context.Context, volunteerID int64) ([]Request, error)
|
|||||||
var requests []Request
|
var requests []Request
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var req Request
|
var req Request
|
||||||
var startsAt, endsAt, createdAt, updatedAt string
|
|
||||||
var reason sql.NullString
|
var reason sql.NullString
|
||||||
var reviewedBy sql.NullInt64
|
var reviewedBy sql.NullInt64
|
||||||
var reviewedAt sql.NullString
|
var reviewedAt sql.NullTime
|
||||||
if err := rows.Scan(&req.ID, &req.VolunteerID, &startsAt, &endsAt, &reason, &req.Status, &reviewedBy, &reviewedAt, &createdAt, &updatedAt); err != nil {
|
if err := rows.Scan(&req.ID, &req.VolunteerID, &req.StartsAt, &req.EndsAt, &reason, &req.Status, &reviewedBy, &reviewedAt, &req.CreatedAt, &req.UpdatedAt); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.StartsAt, _ = time.Parse("2006-01-02 15:04:05", startsAt)
|
|
||||||
req.EndsAt, _ = time.Parse("2006-01-02 15:04:05", endsAt)
|
|
||||||
req.CreatedAt, _ = time.Parse("2006-01-02 15:04:05", createdAt)
|
|
||||||
req.UpdatedAt, _ = time.Parse("2006-01-02 15:04:05", updatedAt)
|
|
||||||
if reason.Valid {
|
if reason.Valid {
|
||||||
req.Reason = reason.String
|
req.Reason = reason.String
|
||||||
}
|
}
|
||||||
@@ -148,8 +137,7 @@ func (s *Store) List(ctx context.Context, volunteerID int64) ([]Request, error)
|
|||||||
req.ReviewedBy = &reviewedBy.Int64
|
req.ReviewedBy = &reviewedBy.Int64
|
||||||
}
|
}
|
||||||
if reviewedAt.Valid {
|
if reviewedAt.Valid {
|
||||||
t, _ := time.Parse("2006-01-02 15:04:05", reviewedAt.String)
|
req.ReviewedAt = &reviewedAt.Time
|
||||||
req.ReviewedAt = &t
|
|
||||||
}
|
}
|
||||||
requests = append(requests, req)
|
requests = append(requests, req)
|
||||||
}
|
}
|
||||||
|
|||||||
1
web/.npmrc
Normal file
1
web/.npmrc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ignore-scripts=true
|
||||||
1281
web/package-lock.json
generated
1281
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@lavamoat/preinstall-always-fail": "^3.0.0",
|
||||||
"react": "^19.2.4",
|
"react": "^19.2.4",
|
||||||
"react-dom": "^19.2.4",
|
"react-dom": "^19.2.4",
|
||||||
"react-router-dom": "^7.13.1"
|
"react-router-dom": "^7.13.1"
|
||||||
@@ -15,6 +16,7 @@
|
|||||||
"test": "vitest run"
|
"test": "vitest run"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@lavamoat/allow-scripts": "^5.0.1",
|
||||||
"@testing-library/dom": "^10.4.1",
|
"@testing-library/dom": "^10.4.1",
|
||||||
"@testing-library/jest-dom": "^6.9.1",
|
"@testing-library/jest-dom": "^6.9.1",
|
||||||
"@testing-library/react": "^16.3.2",
|
"@testing-library/react": "^16.3.2",
|
||||||
@@ -28,5 +30,10 @@
|
|||||||
"typescript": "^6.0.2",
|
"typescript": "^6.0.2",
|
||||||
"vite": "^8.0.8",
|
"vite": "^8.0.8",
|
||||||
"vitest": "^4.1.4"
|
"vitest": "^4.1.4"
|
||||||
|
},
|
||||||
|
"lavamoat": {
|
||||||
|
"allowScripts": {
|
||||||
|
"@lavamoat/preinstall-always-fail": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ export default function TimeOff() {
|
|||||||
onChange={e => setForm(f => ({ ...f, volunteer_id: Number(e.target.value) }))}
|
onChange={e => setForm(f => ({ ...f, volunteer_id: Number(e.target.value) }))}
|
||||||
>
|
>
|
||||||
<option value={0}>Myself</option>
|
<option value={0}>Myself</option>
|
||||||
{volunteers.map(v => (
|
{volunteers.filter(v => v.id !== volunteerID).map(v => (
|
||||||
<option key={v.id} value={v.id}>{v.name}</option>
|
<option key={v.id} value={v.id}>{v.name}</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
@@ -226,8 +226,8 @@ export default function TimeOff() {
|
|||||||
{requests.map(r => (
|
{requests.map(r => (
|
||||||
<tr key={r.id}>
|
<tr key={r.id}>
|
||||||
{role === 'admin' && <td>{volunteerName(r.volunteer_id)}</td>}
|
{role === 'admin' && <td>{volunteerName(r.volunteer_id)}</td>}
|
||||||
<td>{new Date(r.starts_at).toLocaleDateString()}</td>
|
<td>{new Date(r.starts_at).toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' })}</td>
|
||||||
<td>{new Date(r.ends_at).toLocaleDateString()}</td>
|
<td>{new Date(r.ends_at).toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' })}</td>
|
||||||
<td>{r.reason ?? '—'}</td>
|
<td>{r.reason ?? '—'}</td>
|
||||||
<td><span className={statusClass(r.status)}>{r.status}</span></td>
|
<td><span className={statusClass(r.status)}>{r.status}</span></td>
|
||||||
<td>
|
<td>
|
||||||
|
|||||||
Reference in New Issue
Block a user