Ng eventually #1

Open
Sylvain wants to merge 110 commits from ng-eventually into main
9 changed files with 122 additions and 0 deletions
Showing only changes of commit 9e4374b678 - Show all commits
@@ -0,0 +1,7 @@
# Doc-debt — app-architecture
> Presence of a block = doc to update. Processed → delete the block; no blocks left → delete this file.
> One block = one "big change": `why` + `files` + `verify` (leaves to review).
## Raw markers (consolidate into blocks, then delete)
- TOUCHED src/shared/context/FestipodDataContext.tsx @2026-08-17 (session 0b064e8b-1717-421f-a20e-a4318ad217b1)
+9
View File
@@ -0,0 +1,9 @@
# Doc-debt — data-layer
> Presence of a block = doc to update. Processed → delete the block; no blocks left → delete this file.
> One block = one "big change": `why` + `files` + `verify` (leaves to review).
## Raw markers (consolidate into blocks, then delete)
- TOUCHED src/shared/shapes/shex/festipodShapes.shex @2026-08-17 (session 0b064e8b-1717-421f-a20e-a4318ad217b1)
- TOUCHED src/shared/context/FestipodDataContext.tsx @2026-08-17 (session 0b064e8b-1717-421f-a20e-a4318ad217b1)
- TOUCHED src/shared/data/shapeAdapters.ts @2026-08-17 (session 0b064e8b-1717-421f-a20e-a4318ad217b1)
+7
View File
@@ -0,0 +1,7 @@
# Doc-debt — tech-stack
> Presence of a block = doc to update. Processed → delete the block; no blocks left → delete this file.
> One block = one "big change": `why` + `files` + `verify` (leaves to review).
## Raw markers (consolidate into blocks, then delete)
- TOUCHED package.json @2026-08-17 (session 0b064e8b-1717-421f-a20e-a4318ad217b1)
@@ -1178,6 +1178,12 @@ function useNgData(): FestipodDataContextValue {
await openDocumentInbox(eventGraph);
const eventId = await writeEntity(eventGraph, ENTITY_TYPE.event, {
title: str(event.title), description: str(event.description), date: str(event.date),
// `date` is the human LABEL the form composed; these four are the machine
// values it collected, written UNALTERED as the form's own ISO forms
// (`YYYY-MM-DD`, `HH:MM`). They are stored alongside the label, never
// derived from it — the label is display text and cannot be parsed back.
startDate: str(event.startDate), endDate: str(event.endDate),
startTime: str(event.startTime), endTime: str(event.endTime),
location: str(event.location), distance: flt(event.distance),
// No host notion: the creator merely SIGNALS a public event and is NOT
// obliged to participate, so the count starts at 0 (the owner-materializer
@@ -1231,6 +1237,14 @@ function useNgData(): FestipodDataContextValue {
if (updates.title !== undefined) persists.push(updateEntityField(graph, id, 'title', str(updates.title)));
if (updates.description !== undefined) persists.push(updateEntityField(graph, id, 'description', str(updates.description)));
if (updates.date !== undefined) persists.push(updateEntityField(graph, id, 'date', str(updates.date)));
// The machine dates/times travel with the label, not instead of it. A field
// arriving as `''` (the form's empty date input) CLEARS the triple rather than
// leaving a stale value behind — that is `updateEntityField`'s empty handling,
// and it is the right reading here: the user emptied the input.
if (updates.startDate !== undefined) persists.push(updateEntityField(graph, id, 'startDate', str(updates.startDate)));
if (updates.endDate !== undefined) persists.push(updateEntityField(graph, id, 'endDate', str(updates.endDate)));
if (updates.startTime !== undefined) persists.push(updateEntityField(graph, id, 'startTime', str(updates.startTime)));
if (updates.endTime !== undefined) persists.push(updateEntityField(graph, id, 'endTime', str(updates.endTime)));
if (updates.location !== undefined) persists.push(updateEntityField(graph, id, 'location', str(updates.location)));
if (updates.distance !== undefined) persists.push(updateEntityField(graph, id, 'distance', flt(updates.distance)));
await Promise.all(persists).catch(err => console.error(`${logPrefix} persist event update failed:`, err));
+9
View File
@@ -37,6 +37,15 @@ export function adaptEvent(s: UnionSubject): FpEventData {
title: one(s, 'title'),
description: one(s, 'description'),
date: one(s, 'date'),
// The four machine values, read back exactly as stored (`YYYY-MM-DD`, `HH:MM`).
// `undefined` — not `''` — when the triple is absent: the app type declares them
// optional and the screens branch on their PRESENCE (`event.startTime && …`), so
// an event written before these fields existed reads as an event without them
// rather than one whose dates are blank strings.
startDate: one(s, 'startDate') || undefined,
endDate: one(s, 'endDate') || undefined,
startTime: one(s, 'startTime') || undefined,
endTime: one(s, 'endTime') || undefined,
location: one(s, 'location'),
distance: s.props[`${FP}distance`] ? num(s, 'distance') : undefined,
participantCount: num(s, 'participantCount'),
@@ -54,6 +54,50 @@ export const festipodShapesSchema = {
iri: "http://festipod.org/date",
readablePredicate: "date",
},
{
dataTypes: [
{
valType: "string",
},
],
maxCardinality: 1,
minCardinality: 0,
iri: "http://festipod.org/startDate",
readablePredicate: "startDate",
},
{
dataTypes: [
{
valType: "string",
},
],
maxCardinality: 1,
minCardinality: 0,
iri: "http://festipod.org/endDate",
readablePredicate: "endDate",
},
{
dataTypes: [
{
valType: "string",
},
],
maxCardinality: 1,
minCardinality: 0,
iri: "http://festipod.org/startTime",
readablePredicate: "startTime",
},
{
dataTypes: [
{
valType: "string",
},
],
maxCardinality: 1,
minCardinality: 0,
iri: "http://festipod.org/endTime",
readablePredicate: "endTime",
},
{
dataTypes: [
{
@@ -40,6 +40,30 @@ export interface Event {
* Original IRI: http://festipod.org/date
*/
date: string;
/**
* The day the event starts, as the ISO calendar date the form collects (YYYY-MM-DD) — stored unaltered, never derived from fp:date
*
* Original IRI: http://festipod.org/startDate
*/
startDate?: string;
/**
* The day the event ends, as an ISO calendar date (YYYY-MM-DD); absent for a single-day event
*
* Original IRI: http://festipod.org/endDate
*/
endDate?: string;
/**
* The time of day the event starts, as the form collects it (HH:MM)
*
* Original IRI: http://festipod.org/startTime
*/
startTime?: string;
/**
* The time of day the event ends (HH:MM)
*
* Original IRI: http://festipod.org/endTime
*/
endTime?: string;
/**
* The location of the event
*
@@ -10,6 +10,14 @@ fp:Event {
// rdfs:comment "A description of the event" ;
fp:date xsd:string
// rdfs:comment "The display date of the event (e.g. 'Lun. 16 - Ven. 20 fév.')" ;
fp:startDate xsd:string ?
// rdfs:comment "The day the event starts, as the ISO calendar date the form collects (YYYY-MM-DD) — stored unaltered, never derived from fp:date" ;
fp:endDate xsd:string ?
// rdfs:comment "The day the event ends, as an ISO calendar date (YYYY-MM-DD); absent for a single-day event" ;
fp:startTime xsd:string ?
// rdfs:comment "The time of day the event starts, as the form collects it (HH:MM)" ;
fp:endTime xsd:string ?
// rdfs:comment "The time of day the event ends (HH:MM)" ;
fp:location xsd:string
// rdfs:comment "The location of the event" ;
fp:distance xsd:float ?