GET /api/opportunities takes released_from, an RFC 3339 time, and lists only the opportunities whose latest release is at or after it. It works with paging and with changed_after, which keeps the same batch either way; an invalid value is 400. The frontend's filter defaults to 7 days, from midnight UK time, and sends it with every load and catch-up, so a year of opportunities isn't downloaded to show a week's. Changing the days loads the list again; Clear filters goes back to 7.
43 lines
978 B
Go
43 lines
978 B
Go
package api
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
// intParam parses the query parameter text as an integer from low to high,
|
|
// or returns fallback if it is empty. Its error is meant for the client.
|
|
func intParam(text string, fallback, low, high int) (int, error) {
|
|
if text == "" {
|
|
return fallback, nil
|
|
}
|
|
|
|
number, err := strconv.Atoi(text)
|
|
if err != nil || number < low || number > high {
|
|
return 0, fmt.Errorf(
|
|
"parameter must be an integer between %d and %d", low, high,
|
|
)
|
|
}
|
|
|
|
return number, nil
|
|
}
|
|
|
|
// timeParam parses the query parameter name's text as an RFC 3339 time, or
|
|
// returns the zero time if it is empty. Its error is meant for the client.
|
|
func timeParam(name, text string) (time.Time, error) {
|
|
if text == "" {
|
|
return time.Time{}, nil
|
|
}
|
|
|
|
when, err := time.Parse(time.RFC3339, text)
|
|
if err != nil {
|
|
return time.Time{}, fmt.Errorf(
|
|
"%s must be an RFC 3339 date and time, e.g. 2026-10-12T00:00:00+01:00",
|
|
name,
|
|
)
|
|
}
|
|
|
|
return when, nil
|
|
}
|