jansathi-community-schema 0.38.1 → 0.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/feed.d.ts CHANGED
@@ -536,15 +536,94 @@ export declare const voiceBoxOfficerResponseSchema: z.ZodObject<{
536
536
  text: z.ZodString;
537
537
  respondedAt: z.ZodString;
538
538
  }, z.core.$strip>;
539
- /** Location block — denormalised at write time, surfaced inline on
540
- * the card. Lat/lng are intentionally NOT on the wire to keep
541
- * reporter privacy intact; the detail page can fetch them under a
542
- * separate authenticated read if a map view is added. */
543
539
  export declare const voiceBoxLocationSchema: z.ZodObject<{
544
- address: z.ZodString;
545
- district: z.ZodString;
546
- pinCode: z.ZodString;
540
+ country: z.ZodOptional<z.ZodString>;
541
+ state: z.ZodOptional<z.ZodObject<{
542
+ _id: z.ZodOptional<z.ZodString>;
543
+ name: z.ZodString;
544
+ type: z.ZodOptional<z.ZodString>;
545
+ urbanBodyType: z.ZodOptional<z.ZodString>;
546
+ }, z.core.$strip>>;
547
+ division: z.ZodOptional<z.ZodObject<{
548
+ _id: z.ZodOptional<z.ZodString>;
549
+ name: z.ZodString;
550
+ type: z.ZodOptional<z.ZodString>;
551
+ urbanBodyType: z.ZodOptional<z.ZodString>;
552
+ }, z.core.$strip>>;
553
+ district: z.ZodOptional<z.ZodObject<{
554
+ _id: z.ZodOptional<z.ZodString>;
555
+ name: z.ZodString;
556
+ type: z.ZodOptional<z.ZodString>;
557
+ urbanBodyType: z.ZodOptional<z.ZodString>;
558
+ }, z.core.$strip>>;
559
+ subDistrict: z.ZodOptional<z.ZodObject<{
560
+ _id: z.ZodOptional<z.ZodString>;
561
+ name: z.ZodString;
562
+ type: z.ZodOptional<z.ZodString>;
563
+ urbanBodyType: z.ZodOptional<z.ZodString>;
564
+ }, z.core.$strip>>;
565
+ areaType: z.ZodOptional<z.ZodEnum<{
566
+ RURAL: "RURAL";
567
+ URBAN: "URBAN";
568
+ }>>;
569
+ block: z.ZodOptional<z.ZodObject<{
570
+ _id: z.ZodOptional<z.ZodString>;
571
+ name: z.ZodString;
572
+ type: z.ZodOptional<z.ZodString>;
573
+ urbanBodyType: z.ZodOptional<z.ZodString>;
574
+ }, z.core.$strip>>;
575
+ gramPanchayat: z.ZodOptional<z.ZodObject<{
576
+ _id: z.ZodOptional<z.ZodString>;
577
+ name: z.ZodString;
578
+ type: z.ZodOptional<z.ZodString>;
579
+ urbanBodyType: z.ZodOptional<z.ZodString>;
580
+ }, z.core.$strip>>;
581
+ village: z.ZodOptional<z.ZodObject<{
582
+ _id: z.ZodOptional<z.ZodString>;
583
+ name: z.ZodString;
584
+ type: z.ZodOptional<z.ZodString>;
585
+ urbanBodyType: z.ZodOptional<z.ZodString>;
586
+ }, z.core.$strip>>;
587
+ hamlet: z.ZodOptional<z.ZodObject<{
588
+ _id: z.ZodOptional<z.ZodString>;
589
+ name: z.ZodString;
590
+ type: z.ZodOptional<z.ZodString>;
591
+ urbanBodyType: z.ZodOptional<z.ZodString>;
592
+ }, z.core.$strip>>;
593
+ ruralWard: z.ZodOptional<z.ZodObject<{
594
+ _id: z.ZodOptional<z.ZodString>;
595
+ name: z.ZodString;
596
+ type: z.ZodOptional<z.ZodString>;
597
+ urbanBodyType: z.ZodOptional<z.ZodString>;
598
+ }, z.core.$strip>>;
599
+ urbanBody: z.ZodOptional<z.ZodObject<{
600
+ _id: z.ZodOptional<z.ZodString>;
601
+ name: z.ZodString;
602
+ type: z.ZodOptional<z.ZodString>;
603
+ urbanBodyType: z.ZodOptional<z.ZodString>;
604
+ }, z.core.$strip>>;
605
+ urbanWard: z.ZodOptional<z.ZodObject<{
606
+ _id: z.ZodOptional<z.ZodString>;
607
+ name: z.ZodString;
608
+ type: z.ZodOptional<z.ZodString>;
609
+ urbanBodyType: z.ZodOptional<z.ZodString>;
610
+ }, z.core.$strip>>;
611
+ locality: z.ZodOptional<z.ZodObject<{
612
+ _id: z.ZodOptional<z.ZodString>;
613
+ name: z.ZodString;
614
+ type: z.ZodOptional<z.ZodString>;
615
+ urbanBodyType: z.ZodOptional<z.ZodString>;
616
+ }, z.core.$strip>>;
617
+ policeStation: z.ZodOptional<z.ZodObject<{
618
+ _id: z.ZodOptional<z.ZodString>;
619
+ name: z.ZodString;
620
+ type: z.ZodOptional<z.ZodString>;
621
+ urbanBodyType: z.ZodOptional<z.ZodString>;
622
+ }, z.core.$strip>>;
623
+ landmark: z.ZodOptional<z.ZodString>;
624
+ directions: z.ZodOptional<z.ZodString>;
547
625
  }, z.core.$strip>;
626
+ export type VoiceBoxLocation = z.infer<typeof voiceBoxLocationSchema>;
548
627
  /**
549
628
  * Voice-box (complaint or suggestion) item projected into the feed.
550
629
  *
@@ -622,9 +701,91 @@ export declare const voiceBoxFeedItemSchema: z.ZodObject<{
622
701
  }, z.core.$strip>>>;
623
702
  videoLinks: z.ZodOptional<z.ZodArray<z.ZodString>>;
624
703
  location: z.ZodOptional<z.ZodObject<{
625
- address: z.ZodString;
626
- district: z.ZodString;
627
- pinCode: z.ZodString;
704
+ country: z.ZodOptional<z.ZodString>;
705
+ state: z.ZodOptional<z.ZodObject<{
706
+ _id: z.ZodOptional<z.ZodString>;
707
+ name: z.ZodString;
708
+ type: z.ZodOptional<z.ZodString>;
709
+ urbanBodyType: z.ZodOptional<z.ZodString>;
710
+ }, z.core.$strip>>;
711
+ division: z.ZodOptional<z.ZodObject<{
712
+ _id: z.ZodOptional<z.ZodString>;
713
+ name: z.ZodString;
714
+ type: z.ZodOptional<z.ZodString>;
715
+ urbanBodyType: z.ZodOptional<z.ZodString>;
716
+ }, z.core.$strip>>;
717
+ district: z.ZodOptional<z.ZodObject<{
718
+ _id: z.ZodOptional<z.ZodString>;
719
+ name: z.ZodString;
720
+ type: z.ZodOptional<z.ZodString>;
721
+ urbanBodyType: z.ZodOptional<z.ZodString>;
722
+ }, z.core.$strip>>;
723
+ subDistrict: z.ZodOptional<z.ZodObject<{
724
+ _id: z.ZodOptional<z.ZodString>;
725
+ name: z.ZodString;
726
+ type: z.ZodOptional<z.ZodString>;
727
+ urbanBodyType: z.ZodOptional<z.ZodString>;
728
+ }, z.core.$strip>>;
729
+ areaType: z.ZodOptional<z.ZodEnum<{
730
+ RURAL: "RURAL";
731
+ URBAN: "URBAN";
732
+ }>>;
733
+ block: z.ZodOptional<z.ZodObject<{
734
+ _id: z.ZodOptional<z.ZodString>;
735
+ name: z.ZodString;
736
+ type: z.ZodOptional<z.ZodString>;
737
+ urbanBodyType: z.ZodOptional<z.ZodString>;
738
+ }, z.core.$strip>>;
739
+ gramPanchayat: z.ZodOptional<z.ZodObject<{
740
+ _id: z.ZodOptional<z.ZodString>;
741
+ name: z.ZodString;
742
+ type: z.ZodOptional<z.ZodString>;
743
+ urbanBodyType: z.ZodOptional<z.ZodString>;
744
+ }, z.core.$strip>>;
745
+ village: z.ZodOptional<z.ZodObject<{
746
+ _id: z.ZodOptional<z.ZodString>;
747
+ name: z.ZodString;
748
+ type: z.ZodOptional<z.ZodString>;
749
+ urbanBodyType: z.ZodOptional<z.ZodString>;
750
+ }, z.core.$strip>>;
751
+ hamlet: z.ZodOptional<z.ZodObject<{
752
+ _id: z.ZodOptional<z.ZodString>;
753
+ name: z.ZodString;
754
+ type: z.ZodOptional<z.ZodString>;
755
+ urbanBodyType: z.ZodOptional<z.ZodString>;
756
+ }, z.core.$strip>>;
757
+ ruralWard: z.ZodOptional<z.ZodObject<{
758
+ _id: z.ZodOptional<z.ZodString>;
759
+ name: z.ZodString;
760
+ type: z.ZodOptional<z.ZodString>;
761
+ urbanBodyType: z.ZodOptional<z.ZodString>;
762
+ }, z.core.$strip>>;
763
+ urbanBody: z.ZodOptional<z.ZodObject<{
764
+ _id: z.ZodOptional<z.ZodString>;
765
+ name: z.ZodString;
766
+ type: z.ZodOptional<z.ZodString>;
767
+ urbanBodyType: z.ZodOptional<z.ZodString>;
768
+ }, z.core.$strip>>;
769
+ urbanWard: z.ZodOptional<z.ZodObject<{
770
+ _id: z.ZodOptional<z.ZodString>;
771
+ name: z.ZodString;
772
+ type: z.ZodOptional<z.ZodString>;
773
+ urbanBodyType: z.ZodOptional<z.ZodString>;
774
+ }, z.core.$strip>>;
775
+ locality: z.ZodOptional<z.ZodObject<{
776
+ _id: z.ZodOptional<z.ZodString>;
777
+ name: z.ZodString;
778
+ type: z.ZodOptional<z.ZodString>;
779
+ urbanBodyType: z.ZodOptional<z.ZodString>;
780
+ }, z.core.$strip>>;
781
+ policeStation: z.ZodOptional<z.ZodObject<{
782
+ _id: z.ZodOptional<z.ZodString>;
783
+ name: z.ZodString;
784
+ type: z.ZodOptional<z.ZodString>;
785
+ urbanBodyType: z.ZodOptional<z.ZodString>;
786
+ }, z.core.$strip>>;
787
+ landmark: z.ZodOptional<z.ZodString>;
788
+ directions: z.ZodOptional<z.ZodString>;
628
789
  }, z.core.$strip>>;
629
790
  hasReporterPhone: z.ZodOptional<z.ZodBoolean>;
630
791
  officerResponse: z.ZodOptional<z.ZodNullable<z.ZodObject<{
@@ -1033,9 +1194,91 @@ export declare const feedItemSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1033
1194
  }, z.core.$strip>>>;
1034
1195
  videoLinks: z.ZodOptional<z.ZodArray<z.ZodString>>;
1035
1196
  location: z.ZodOptional<z.ZodObject<{
1036
- address: z.ZodString;
1037
- district: z.ZodString;
1038
- pinCode: z.ZodString;
1197
+ country: z.ZodOptional<z.ZodString>;
1198
+ state: z.ZodOptional<z.ZodObject<{
1199
+ _id: z.ZodOptional<z.ZodString>;
1200
+ name: z.ZodString;
1201
+ type: z.ZodOptional<z.ZodString>;
1202
+ urbanBodyType: z.ZodOptional<z.ZodString>;
1203
+ }, z.core.$strip>>;
1204
+ division: z.ZodOptional<z.ZodObject<{
1205
+ _id: z.ZodOptional<z.ZodString>;
1206
+ name: z.ZodString;
1207
+ type: z.ZodOptional<z.ZodString>;
1208
+ urbanBodyType: z.ZodOptional<z.ZodString>;
1209
+ }, z.core.$strip>>;
1210
+ district: z.ZodOptional<z.ZodObject<{
1211
+ _id: z.ZodOptional<z.ZodString>;
1212
+ name: z.ZodString;
1213
+ type: z.ZodOptional<z.ZodString>;
1214
+ urbanBodyType: z.ZodOptional<z.ZodString>;
1215
+ }, z.core.$strip>>;
1216
+ subDistrict: z.ZodOptional<z.ZodObject<{
1217
+ _id: z.ZodOptional<z.ZodString>;
1218
+ name: z.ZodString;
1219
+ type: z.ZodOptional<z.ZodString>;
1220
+ urbanBodyType: z.ZodOptional<z.ZodString>;
1221
+ }, z.core.$strip>>;
1222
+ areaType: z.ZodOptional<z.ZodEnum<{
1223
+ RURAL: "RURAL";
1224
+ URBAN: "URBAN";
1225
+ }>>;
1226
+ block: z.ZodOptional<z.ZodObject<{
1227
+ _id: z.ZodOptional<z.ZodString>;
1228
+ name: z.ZodString;
1229
+ type: z.ZodOptional<z.ZodString>;
1230
+ urbanBodyType: z.ZodOptional<z.ZodString>;
1231
+ }, z.core.$strip>>;
1232
+ gramPanchayat: z.ZodOptional<z.ZodObject<{
1233
+ _id: z.ZodOptional<z.ZodString>;
1234
+ name: z.ZodString;
1235
+ type: z.ZodOptional<z.ZodString>;
1236
+ urbanBodyType: z.ZodOptional<z.ZodString>;
1237
+ }, z.core.$strip>>;
1238
+ village: z.ZodOptional<z.ZodObject<{
1239
+ _id: z.ZodOptional<z.ZodString>;
1240
+ name: z.ZodString;
1241
+ type: z.ZodOptional<z.ZodString>;
1242
+ urbanBodyType: z.ZodOptional<z.ZodString>;
1243
+ }, z.core.$strip>>;
1244
+ hamlet: z.ZodOptional<z.ZodObject<{
1245
+ _id: z.ZodOptional<z.ZodString>;
1246
+ name: z.ZodString;
1247
+ type: z.ZodOptional<z.ZodString>;
1248
+ urbanBodyType: z.ZodOptional<z.ZodString>;
1249
+ }, z.core.$strip>>;
1250
+ ruralWard: z.ZodOptional<z.ZodObject<{
1251
+ _id: z.ZodOptional<z.ZodString>;
1252
+ name: z.ZodString;
1253
+ type: z.ZodOptional<z.ZodString>;
1254
+ urbanBodyType: z.ZodOptional<z.ZodString>;
1255
+ }, z.core.$strip>>;
1256
+ urbanBody: z.ZodOptional<z.ZodObject<{
1257
+ _id: z.ZodOptional<z.ZodString>;
1258
+ name: z.ZodString;
1259
+ type: z.ZodOptional<z.ZodString>;
1260
+ urbanBodyType: z.ZodOptional<z.ZodString>;
1261
+ }, z.core.$strip>>;
1262
+ urbanWard: z.ZodOptional<z.ZodObject<{
1263
+ _id: z.ZodOptional<z.ZodString>;
1264
+ name: z.ZodString;
1265
+ type: z.ZodOptional<z.ZodString>;
1266
+ urbanBodyType: z.ZodOptional<z.ZodString>;
1267
+ }, z.core.$strip>>;
1268
+ locality: z.ZodOptional<z.ZodObject<{
1269
+ _id: z.ZodOptional<z.ZodString>;
1270
+ name: z.ZodString;
1271
+ type: z.ZodOptional<z.ZodString>;
1272
+ urbanBodyType: z.ZodOptional<z.ZodString>;
1273
+ }, z.core.$strip>>;
1274
+ policeStation: z.ZodOptional<z.ZodObject<{
1275
+ _id: z.ZodOptional<z.ZodString>;
1276
+ name: z.ZodString;
1277
+ type: z.ZodOptional<z.ZodString>;
1278
+ urbanBodyType: z.ZodOptional<z.ZodString>;
1279
+ }, z.core.$strip>>;
1280
+ landmark: z.ZodOptional<z.ZodString>;
1281
+ directions: z.ZodOptional<z.ZodString>;
1039
1282
  }, z.core.$strip>>;
1040
1283
  hasReporterPhone: z.ZodOptional<z.ZodBoolean>;
1041
1284
  officerResponse: z.ZodOptional<z.ZodNullable<z.ZodObject<{
@@ -1829,9 +2072,91 @@ export declare const feedResponseSchema: z.ZodObject<{
1829
2072
  }, z.core.$strip>>>;
1830
2073
  videoLinks: z.ZodOptional<z.ZodArray<z.ZodString>>;
1831
2074
  location: z.ZodOptional<z.ZodObject<{
1832
- address: z.ZodString;
1833
- district: z.ZodString;
1834
- pinCode: z.ZodString;
2075
+ country: z.ZodOptional<z.ZodString>;
2076
+ state: z.ZodOptional<z.ZodObject<{
2077
+ _id: z.ZodOptional<z.ZodString>;
2078
+ name: z.ZodString;
2079
+ type: z.ZodOptional<z.ZodString>;
2080
+ urbanBodyType: z.ZodOptional<z.ZodString>;
2081
+ }, z.core.$strip>>;
2082
+ division: z.ZodOptional<z.ZodObject<{
2083
+ _id: z.ZodOptional<z.ZodString>;
2084
+ name: z.ZodString;
2085
+ type: z.ZodOptional<z.ZodString>;
2086
+ urbanBodyType: z.ZodOptional<z.ZodString>;
2087
+ }, z.core.$strip>>;
2088
+ district: z.ZodOptional<z.ZodObject<{
2089
+ _id: z.ZodOptional<z.ZodString>;
2090
+ name: z.ZodString;
2091
+ type: z.ZodOptional<z.ZodString>;
2092
+ urbanBodyType: z.ZodOptional<z.ZodString>;
2093
+ }, z.core.$strip>>;
2094
+ subDistrict: z.ZodOptional<z.ZodObject<{
2095
+ _id: z.ZodOptional<z.ZodString>;
2096
+ name: z.ZodString;
2097
+ type: z.ZodOptional<z.ZodString>;
2098
+ urbanBodyType: z.ZodOptional<z.ZodString>;
2099
+ }, z.core.$strip>>;
2100
+ areaType: z.ZodOptional<z.ZodEnum<{
2101
+ RURAL: "RURAL";
2102
+ URBAN: "URBAN";
2103
+ }>>;
2104
+ block: z.ZodOptional<z.ZodObject<{
2105
+ _id: z.ZodOptional<z.ZodString>;
2106
+ name: z.ZodString;
2107
+ type: z.ZodOptional<z.ZodString>;
2108
+ urbanBodyType: z.ZodOptional<z.ZodString>;
2109
+ }, z.core.$strip>>;
2110
+ gramPanchayat: z.ZodOptional<z.ZodObject<{
2111
+ _id: z.ZodOptional<z.ZodString>;
2112
+ name: z.ZodString;
2113
+ type: z.ZodOptional<z.ZodString>;
2114
+ urbanBodyType: z.ZodOptional<z.ZodString>;
2115
+ }, z.core.$strip>>;
2116
+ village: z.ZodOptional<z.ZodObject<{
2117
+ _id: z.ZodOptional<z.ZodString>;
2118
+ name: z.ZodString;
2119
+ type: z.ZodOptional<z.ZodString>;
2120
+ urbanBodyType: z.ZodOptional<z.ZodString>;
2121
+ }, z.core.$strip>>;
2122
+ hamlet: z.ZodOptional<z.ZodObject<{
2123
+ _id: z.ZodOptional<z.ZodString>;
2124
+ name: z.ZodString;
2125
+ type: z.ZodOptional<z.ZodString>;
2126
+ urbanBodyType: z.ZodOptional<z.ZodString>;
2127
+ }, z.core.$strip>>;
2128
+ ruralWard: z.ZodOptional<z.ZodObject<{
2129
+ _id: z.ZodOptional<z.ZodString>;
2130
+ name: z.ZodString;
2131
+ type: z.ZodOptional<z.ZodString>;
2132
+ urbanBodyType: z.ZodOptional<z.ZodString>;
2133
+ }, z.core.$strip>>;
2134
+ urbanBody: z.ZodOptional<z.ZodObject<{
2135
+ _id: z.ZodOptional<z.ZodString>;
2136
+ name: z.ZodString;
2137
+ type: z.ZodOptional<z.ZodString>;
2138
+ urbanBodyType: z.ZodOptional<z.ZodString>;
2139
+ }, z.core.$strip>>;
2140
+ urbanWard: z.ZodOptional<z.ZodObject<{
2141
+ _id: z.ZodOptional<z.ZodString>;
2142
+ name: z.ZodString;
2143
+ type: z.ZodOptional<z.ZodString>;
2144
+ urbanBodyType: z.ZodOptional<z.ZodString>;
2145
+ }, z.core.$strip>>;
2146
+ locality: z.ZodOptional<z.ZodObject<{
2147
+ _id: z.ZodOptional<z.ZodString>;
2148
+ name: z.ZodString;
2149
+ type: z.ZodOptional<z.ZodString>;
2150
+ urbanBodyType: z.ZodOptional<z.ZodString>;
2151
+ }, z.core.$strip>>;
2152
+ policeStation: z.ZodOptional<z.ZodObject<{
2153
+ _id: z.ZodOptional<z.ZodString>;
2154
+ name: z.ZodString;
2155
+ type: z.ZodOptional<z.ZodString>;
2156
+ urbanBodyType: z.ZodOptional<z.ZodString>;
2157
+ }, z.core.$strip>>;
2158
+ landmark: z.ZodOptional<z.ZodString>;
2159
+ directions: z.ZodOptional<z.ZodString>;
1835
2160
  }, z.core.$strip>>;
1836
2161
  hasReporterPhone: z.ZodOptional<z.ZodBoolean>;
1837
2162
  officerResponse: z.ZodOptional<z.ZodNullable<z.ZodObject<{
@@ -1 +1 @@
1
- {"version":3,"file":"feed.d.ts","sourceRoot":"","sources":["../src/feed.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"feed.d.ts","sourceRoot":"","sources":["../src/feed.ts"],"names":[],"mappings":"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"}
package/dist/feed.js CHANGED
@@ -360,14 +360,44 @@ export const voiceBoxOfficerResponseSchema = z.object({
360
360
  text: z.string().max(280),
361
361
  respondedAt: z.string().datetime(),
362
362
  });
363
- /** Location block denormalised at write time, surfaced inline on
364
- * the card. Lat/lng are intentionally NOT on the wire to keep
365
- * reporter privacy intact; the detail page can fetch them under a
366
- * separate authenticated read if a map view is added. */
363
+ /** Structured incident-location for a suggestion/complaint report.
364
+ *
365
+ * Same shape as `lostFoundLocationSchema` area-hierarchy snapshot
366
+ * the user picked in the location drawer (state / district /
367
+ * locality / etc.) plus optional `landmark` + `directions` free-text.
368
+ * Lat/lng intentionally NOT on the wire to keep reporter privacy
369
+ * intact; the card composes a single human-readable string from
370
+ * these via `formatLostFoundLocation` (the helper is shape-agnostic).
371
+ *
372
+ * Legacy rows authored before this migration carry a flat
373
+ * `{ address, district, pinCode }` shape on the model; the feed
374
+ * projector coerces those into `{ landmark: address, district:
375
+ * { name: district } }` on the way out so consumers only see one
376
+ * shape. */
377
+ const voiceBoxAreaRefSchema = z.object({
378
+ _id: z.string().optional(),
379
+ name: z.string(),
380
+ type: z.string().optional(),
381
+ urbanBodyType: z.string().optional(),
382
+ });
367
383
  export const voiceBoxLocationSchema = z.object({
368
- address: z.string(),
369
- district: z.string(),
370
- pinCode: z.string(),
384
+ country: z.string().optional(),
385
+ state: voiceBoxAreaRefSchema.optional(),
386
+ division: voiceBoxAreaRefSchema.optional(),
387
+ district: voiceBoxAreaRefSchema.optional(),
388
+ subDistrict: voiceBoxAreaRefSchema.optional(),
389
+ areaType: z.enum(['RURAL', 'URBAN']).optional(),
390
+ block: voiceBoxAreaRefSchema.optional(),
391
+ gramPanchayat: voiceBoxAreaRefSchema.optional(),
392
+ village: voiceBoxAreaRefSchema.optional(),
393
+ hamlet: voiceBoxAreaRefSchema.optional(),
394
+ ruralWard: voiceBoxAreaRefSchema.optional(),
395
+ urbanBody: voiceBoxAreaRefSchema.optional(),
396
+ urbanWard: voiceBoxAreaRefSchema.optional(),
397
+ locality: voiceBoxAreaRefSchema.optional(),
398
+ policeStation: voiceBoxAreaRefSchema.optional(),
399
+ landmark: z.string().max(200).optional(),
400
+ directions: z.string().max(500).optional(),
371
401
  });
372
402
  /**
373
403
  * Voice-box (complaint or suggestion) item projected into the feed.
@@ -397,7 +427,9 @@ export const voiceBoxFeedItemSchema = z.object({
397
427
  priority: voiceBoxPrioritySchema.optional(),
398
428
  /** Lifecycle status. */
399
429
  status: voiceBoxStatusSchema.optional(),
400
- /** Photo evidence (up to 10 per the model). */
430
+ /** Photo evidence cap is 3 (matches the form policy). Legacy
431
+ * rows authored before the cap was tightened may carry up to 10;
432
+ * consumers should clamp at render time if they care. */
401
433
  images: z.array(z.string().url()).max(10).optional(),
402
434
  /** Voice-note attachment. */
403
435
  audio: voiceBoxAudioSchema.nullable().optional(),
package/dist/feed.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"feed.js","sourceRoot":"","sources":["../src/feed.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Feed wire shapes — polymorphic union of community posts, lost-and-\n * found reports, and voice-box (complaints + suggestions).\n *\n * The feed is a SINGLE list typed as `FeedItem = Post | LostFound | VoiceBox`.\n * The client discriminates on `contentKind` and renders the matching\n * card component.\n *\n * Strategy notes (server-side):\n * - Read-time fanout. The server runs ONE parallel query per kind\n * filtered by the same area-lineage match and the same cascade-\n * upward visibility rule, then merges and sorts by `hot` score.\n * - Cursor-based pagination. The cursor is opaque (base64 of\n * `<sortKey>|<_id>`) so we can swap sort algorithms without a\n * breaking change.\n * - LostFound / VoiceBox shapes are pruned to the fields the feed\n * card needs — they keep their richer detail-page shape in their\n * own schemas (lost-found-schema, voice-box-schema if/when those\n * get factored out).\n *\n * @module community-schema/feed\n */\n\nimport { z } from 'zod';\nimport { FEED_PAGE_SIZE } from './constants.js';\nimport { crowdfundingFeedItemSchema } from './crowdfunding.js';\nimport { voteValueSchema } from './engagement.js';\nimport { feedSortSchema, visibilityLevelSchema } from './enums.js';\nimport { communityPollFeedItemSchema } from './poll.js';\nimport { communityPostWireSchema, postAuthorSnapshotSchema } from './post.js';\n\n// ─── Per-kind feed envelopes ───────────────────────────────────────────────\n\n/**\n * Lost-and-found category enum — mirrors the reform-backend\n * `LOST_FOUND_CATEGORY` map. Stable English snake_case slugs; the\n * card maps each to an icon + localised label.\n */\nexport const LOST_FOUND_CATEGORY_VALUES = [\n 'electronics',\n 'jewelry',\n 'documents',\n 'clothing',\n 'pets',\n 'bags_luggage',\n 'keys',\n 'wallet_purse',\n 'phone',\n 'id_cards',\n 'other',\n] as const;\nexport const lostFoundCategorySchema = z.enum(LOST_FOUND_CATEGORY_VALUES);\nexport type LostFoundCategory = z.infer<typeof lostFoundCategorySchema>;\n\n/**\n * Lost-and-found status — `active` is the in-feed state, `resolved`\n * means a claim closed the report, `expired` means the auto-archive\n * window passed.\n */\nexport const LOST_FOUND_STATUS_VALUES = ['active', 'resolved', 'expired'] as const;\nexport const lostFoundStatusSchema = z.enum(LOST_FOUND_STATUS_VALUES);\nexport type LostFoundStatus = z.infer<typeof lostFoundStatusSchema>;\n\n/**\n * Slim area reference snapshot — mirrors the donations PickupAddress\n * AreaRefSnapshot. Stored on lost-found reports so the location pill\n * can show \"Locality, District, State\" without an Area lookup.\n */\nconst lostFoundAreaRefSchema = z.object({\n _id: z.string().optional(),\n name: z.string(),\n type: z.string().optional(),\n urbanBodyType: z.string().optional(),\n});\n\n/**\n * Structured location for a lost-found report. Mirrors the donations\n * pickup address with deliberate omissions: lost-found reports\n * describe an INCIDENT spot, not a delivery address, so\n * - `housePlotDetails` and `pincode` are dropped (no postal logistics);\n * - `coords` are dropped (no GPS capture — the reporter usually isn't\n * standing at the spot when they file the report);\n * - `landmark` + `directions` are kept (the user's free-text\n * description of where).\n *\n * Every field is optional so a sparse report (\"I lost it somewhere in\n * Mumbai\") is still valid.\n */\nexport const lostFoundLocationSchema = z.object({\n country: z.string().optional(),\n state: lostFoundAreaRefSchema.optional(),\n division: lostFoundAreaRefSchema.optional(),\n district: lostFoundAreaRefSchema.optional(),\n subDistrict: lostFoundAreaRefSchema.optional(),\n areaType: z.enum(['RURAL', 'URBAN']).optional(),\n block: lostFoundAreaRefSchema.optional(),\n gramPanchayat: lostFoundAreaRefSchema.optional(),\n village: lostFoundAreaRefSchema.optional(),\n hamlet: lostFoundAreaRefSchema.optional(),\n ruralWard: lostFoundAreaRefSchema.optional(),\n urbanBody: lostFoundAreaRefSchema.optional(),\n urbanWard: lostFoundAreaRefSchema.optional(),\n locality: lostFoundAreaRefSchema.optional(),\n policeStation: lostFoundAreaRefSchema.optional(),\n /** Free-text landmark, e.g. \"near the bus stop\". */\n landmark: z.string().max(200).optional(),\n /** Free-text additional context, e.g. \"south-west corner near the\n * parking lot\". Stored as `directions` on the model to match the\n * donations naming so the shared address normaliser works without\n * a per-feature aliasing layer. */\n directions: z.string().max(500).optional(),\n});\nexport type LostFoundLocation = z.infer<typeof lostFoundLocationSchema>;\n\n/** HH:MM-format time window on the report's date. Either endpoint may\n * be omitted, so the user can record \"after 2pm\", \"before 4pm\", or\n * \"between 2 and 4pm\" with the same shape. */\nexport const lostFoundTimeRangeSchema = z\n .object({\n startTime: z\n .string()\n .regex(/^([01]\\d|2[0-3]):[0-5]\\d$/, 'startTime must be HH:MM (24-hour)')\n .optional(),\n endTime: z\n .string()\n .regex(/^([01]\\d|2[0-3]):[0-5]\\d$/, 'endTime must be HH:MM (24-hour)')\n .optional(),\n })\n // At least one endpoint must be set — an empty `{}` adds no\n // information and is omitted by the form before submit.\n .refine((tr) => Boolean(tr.startTime || tr.endTime), {\n message: 'timeRange must include at least startTime or endTime',\n });\nexport type LostFoundTimeRange = z.infer<typeof lostFoundTimeRangeSchema>;\n\n/**\n * Lost-and-found item projected into the feed.\n *\n * v3 wire — extended to carry every field the production card renders\n * inline, so a single feed read serves the whole row. The detail page\n * (which loads `IReformLostFoundReport` directly) carries the long\n * tail of fields like `creatorName`, `resolvedWith`, audit logs.\n */\nexport const lostFoundFeedItemSchema = z.object({\n _id: z.string(),\n contentKind: z.literal('lost_found'),\n author: postAuthorSnapshotSchema,\n\n /** `'lost'` or `'found'` — drives the ribbon banner colour. */\n kind: z.enum(['lost', 'found']),\n title: z.string(),\n description: z.string(),\n\n // ─── v3 additions (all optional for backward compat) ─────────────\n // Live consumers reading the v1 wire keep working because every\n // new field is optional. The v3 projector populates them; the v3\n // card reads them. As consumers migrate to v3, the optionality can\n // tighten in a future minor bump.\n /** Curated category — drives the category icon + label chip.\n * Optional only until the v3 projector ships. */\n category: lostFoundCategorySchema.optional(),\n /** All images attached to the report (up to 5). The card renders a\n * swipeable carousel; the legacy `imageUrl` field below is kept\n * as a deprecated alias for `images[0]`. */\n images: z.array(z.string().url()).max(5).optional(),\n /** Where the item was lost / found.\n *\n * Structured shape: the area-hierarchy snapshot the user picked in\n * the LostFoundLocationDrawer plus optional `landmark` /\n * `directions` free-text. The card composes a single human-readable\n * string from these for the location pill.\n *\n * Backward compat: rows created before this migration carry a plain\n * string. The projector converts those legacy values to\n * `{ landmark: <string> }` on the way out so the wire always speaks\n * the new shape and the card stays simple. */\n location: lostFoundLocationSchema.optional(),\n /** Event date — when the item was lost / found. Distinct from\n * `createdAt`. */\n date: z.string().datetime().optional(),\n /** Optional time window on the report's `date` when the user\n * believes the item was lost or found. Both endpoints are HH:MM\n * strings (24-hour) and both are optional so the user can supply\n * just a start, just an end, or both. Omitted entirely when the\n * user couldn't narrow it down to a time. */\n timeRange: lostFoundTimeRangeSchema.optional(),\n /** For `kind === 'found'`: instructions on where to collect the\n * item. Null on `lost` reports. */\n collectionPoint: z.string().nullable().optional(),\n /** Public dial-back number captured on the report. */\n contactPhone: z.string().nullable().optional(),\n /** Lifecycle status. */\n status: lostFoundStatusSchema.optional(),\n /** Distinct-claimant count — drives the \"3 claims\" social-proof\n * chip. Maintained by the LostFoundClaim service. */\n claimCount: z.number().int().nonnegative().optional(),\n /** Free-text reward note (\"₹2,500\", \"Will treat to dinner\"). */\n rewardOffered: z.string().max(40).nullable().optional(),\n\n /** Deprecated single primary image. New consumers should read\n * `images[0]`; kept on the wire for the v1 card path. */\n imageUrl: z.string().url().optional(),\n\n /** Inherited engagement axis — same shape as posts. Score is the\n * signed net (upvotes - downvotes), can be negative. */\n score: z.number().int(),\n commentCount: z.number().int().nonnegative(),\n repostCount: z.number().int().nonnegative(),\n reactionCounts: z.record(z.string(), z.number().int().nonnegative()),\n\n createdAt: z.string().datetime(),\n\n viewer: z\n .object({\n vote: voteValueSchema.nullable(),\n reaction: z.string().nullable(),\n bookmarked: z.boolean(),\n isAuthor: z.boolean(),\n reposted: z.boolean(),\n })\n .optional(),\n});\nexport type LostFoundFeedItem = z.infer<typeof lostFoundFeedItemSchema>;\n\n/**\n * Donate-item status — mirrors the reform-backend\n * `ITEM_DONATION_STATUS` enum. `CANCELLED` is a terminal out-of-band\n * state (donor or admin withdrew the listing).\n */\nexport const DONATE_ITEM_STATUS_VALUES = [\n 'PENDING',\n 'VERIFIED',\n 'AT_CENTER',\n 'CANCELLED',\n 'DONATED',\n] as const;\nexport const donateItemStatusSchema = z.enum(DONATE_ITEM_STATUS_VALUES);\nexport type DonateItemStatus = z.infer<typeof donateItemStatusSchema>;\n\n/**\n * Item-condition labels surfaced on the chip. Mirrors the reform-\n * backend `ITEM_CONDITION` enum.\n */\nexport const DONATE_ITEM_CONDITION_VALUES = [\n 'NEW',\n 'LIKE_NEW',\n 'GOOD',\n 'FAIR',\n 'OLD_FUNCTIONAL',\n 'NEEDS_MINOR_REPAIR',\n 'NEEDS_MAJOR_REPAIR',\n 'FOR_PARTS',\n] as const;\nexport const donateItemConditionSchema = z.enum(DONATE_ITEM_CONDITION_VALUES);\nexport type DonateItemCondition = z.infer<typeof donateItemConditionSchema>;\n\n/** Audit summary shapes — short, denormalised projections of the\n * underlying pipeline blocks. The detail page carries the full\n * notes; the feed card just needs the \"who + when\". */\nexport const donateAuditByAtSchema = z.object({\n /** Display name of the person who performed the step. */\n byName: z.string(),\n /** When the step happened. */\n at: z.string().datetime(),\n});\nexport const donateAuditAtSchema = z.object({ at: z.string().datetime() });\nexport const donateDonatedToSchema = z.object({\n /** Name of the recipient (person or institution). */\n name: z.string(),\n at: z.string().datetime(),\n});\n\n/**\n * Donated-item listing projected into the feed.\n *\n * v3 wire — extended to carry every field the production card renders\n * inline. The full pickup-address sub-doc, verification notes, and\n * pipeline notes stay on the detail page.\n */\nexport const donateItemFeedItemSchema = z.object({\n _id: z.string(),\n contentKind: z.literal('donate_item'),\n /** Author of the donation. When `isAnonymous` is true, the wire\n * still ships a placeholder author (initials + neutral gradient,\n * no real `username` / `displayName`) — the server scrubs PII so\n * the wire is the privacy boundary, not the card. */\n author: postAuthorSnapshotSchema,\n\n /** Display name of the item. */\n itemName: z.string(),\n /** Optional free-text description. */\n description: z.string().optional(),\n /** Free-text category for now (the backend enum is widening; keeping\n * this open avoids a schema break each time a category is added). */\n category: z.string(),\n /** Item condition. Optional only because legacy rows pre-date the\n * field; new writes always populate it. */\n condition: donateItemConditionSchema.optional(),\n\n /** Lifecycle status — `string` for backward compat with v1\n * consumers that received an open string; v3 consumers should\n * refine against `donateItemStatusSchema`. */\n status: z.string(),\n\n // ─── v3 additions (all optional for backward compat) ─────────────\n /** Estimated worth in INR (₹). Null when the donor declined. */\n estimatedWorthInr: z.number().int().nullable().optional(),\n /** All photos attached to the donation (up to 3). */\n photos: z.array(z.string().url()).max(3).optional(),\n /** Donor opted to hide identity on the public feed. */\n isAnonymous: z.boolean().optional(),\n /** Distance from the viewer's `currentLocation` in km. */\n distanceKm: z.number().nonnegative().nullable().optional(),\n /** Date after which the donor is no longer available. */\n availableUntil: z.string().datetime().nullable().optional(),\n /** Pipeline audit summaries — each null when the step hasn't\n * happened yet. The card progressively reveals the blocks as the\n * donation moves through the pipeline. */\n verification: donateAuditByAtSchema.nullable().optional(),\n pickup: donateAuditByAtSchema.nullable().optional(),\n centerSubmission: donateAuditAtSchema.nullable().optional(),\n donatedTo: donateDonatedToSchema.nullable().optional(),\n\n /** Deprecated single primary image. New consumers should read\n * `photos[0]`; kept on the wire for the v1 card path. */\n imageUrl: z.string().url().optional(),\n\n score: z.number().int(),\n commentCount: z.number().int().nonnegative(),\n repostCount: z.number().int().nonnegative(),\n reactionCounts: z.record(z.string(), z.number().int().nonnegative()),\n\n createdAt: z.string().datetime(),\n\n viewer: z\n .object({\n vote: voteValueSchema.nullable(),\n reaction: z.string().nullable(),\n bookmarked: z.boolean(),\n isAuthor: z.boolean(),\n reposted: z.boolean(),\n })\n .optional(),\n});\nexport type DonateItemFeedItem = z.infer<typeof donateItemFeedItemSchema>;\n\n/**\n * Voice-box priority — mirrors `IReformIssueReport.priority`.\n * Drives the side-stripe colour on the complaint card.\n */\nexport const VOICE_BOX_PRIORITY_VALUES = ['low', 'medium', 'high', 'critical'] as const;\nexport const voiceBoxPrioritySchema = z.enum(VOICE_BOX_PRIORITY_VALUES);\nexport type VoiceBoxPriority = z.infer<typeof voiceBoxPrioritySchema>;\n\n/**\n * Voice-box lifecycle status. Five states matching the model — the\n * card surfaces `pending`/`under_review`/`in_progress` as in-flight\n * pills, `resolved` as a green resolution footer, `rejected` as\n * neutral with an explanation.\n */\nexport const VOICE_BOX_STATUS_VALUES = [\n 'pending',\n 'under_review',\n 'in_progress',\n 'resolved',\n 'rejected',\n] as const;\nexport const voiceBoxStatusSchema = z.enum(VOICE_BOX_STATUS_VALUES);\nexport type VoiceBoxStatus = z.infer<typeof voiceBoxStatusSchema>;\n\n/** Inline-playable audio attachment (voice complaint). The model\n * stores `IssueAudio` with `url + gcpPath + uploadedAt + duration`;\n * the wire is trimmed to what the card needs to render the WhatsApp-\n * style voice note bar. */\nexport const voiceBoxAudioSchema = z.object({\n url: z.string().url(),\n /** Duration in seconds. Drives the bar's duration chip. */\n durationSec: z.number().positive(),\n});\n\n/** Inline-playable video attachment (single native upload). */\nexport const voiceBoxVideoSchema = z.object({\n url: z.string().url(),\n thumbnailUrl: z.string().url(),\n durationSec: z.number().positive(),\n});\n\n/** Officer-response summary projected onto the feed wire so the card\n * can render the sky-blue \"Official response\" block without a\n * second round trip. Full text + reply audit log live on the\n * detail page. */\nexport const voiceBoxOfficerResponseSchema = z.object({\n /** Display name of the assigned officer. */\n officerName: z.string(),\n /** Officer's designation (Pradhan / Mayor / Junior Engineer / ...).\n * Null when the assigned user has no civic designation. */\n designation: z.string().nullable(),\n /** Truncated response text — max 280 chars. The full note lives on\n * the detail page. */\n text: z.string().max(280),\n respondedAt: z.string().datetime(),\n});\n\n/** Location block — denormalised at write time, surfaced inline on\n * the card. Lat/lng are intentionally NOT on the wire to keep\n * reporter privacy intact; the detail page can fetch them under a\n * separate authenticated read if a map view is added. */\nexport const voiceBoxLocationSchema = z.object({\n address: z.string(),\n district: z.string(),\n pinCode: z.string(),\n});\n\n/**\n * Voice-box (complaint or suggestion) item projected into the feed.\n *\n * v3 wire — extended from the v1 stub to carry every field the\n * civic-grade card renders. Privacy: `reporterPhone` is replaced by a\n * `hasReporterPhone` boolean so the public feed can show a Call CTA\n * without exposing the raw number; the detail page issues the\n * authenticated read that returns the actual tel: target.\n */\nexport const voiceBoxFeedItemSchema = z.object({\n _id: z.string(),\n contentKind: z.literal('voice_box'),\n author: postAuthorSnapshotSchema,\n\n /** `'complaint'` or `'suggestion'` — drives the card chrome (priority\n * stripe vs. Reddit-vote rail). */\n kind: z.enum(['complaint', 'suggestion']),\n title: z.string(),\n description: z.string(),\n\n // ─── v3 additions (all optional for backward compat) ─────────────\n // The v1 wire shipped only `kind / title / description`. The v3\n // card needs the full set; until the projector is upgraded the\n // fields here remain optional so production reads still validate.\n /** Free-text civic category (Water Supply / Electricity / ...). */\n category: z.string().optional(),\n /** Severity — drives the priority side stripe. */\n priority: voiceBoxPrioritySchema.optional(),\n /** Lifecycle status. */\n status: voiceBoxStatusSchema.optional(),\n\n /** Photo evidence (up to 10 per the model). */\n images: z.array(z.string().url()).max(10).optional(),\n /** Voice-note attachment. */\n audio: voiceBoxAudioSchema.nullable().optional(),\n /** Single native video upload. */\n video: voiceBoxVideoSchema.nullable().optional(),\n /** External video links (YouTube / Vimeo). */\n videoLinks: z.array(z.string().url()).max(5).optional(),\n\n /** Address breakdown the card renders. */\n location: voiceBoxLocationSchema.optional(),\n\n /** Whether the report has a public-contact phone. The Call pill\n * links to a separate authenticated read that resolves the\n * number — keeping the raw phone out of the cached feed\n * response. */\n hasReporterPhone: z.boolean().optional(),\n\n /** Assigned-officer response summary. */\n officerResponse: voiceBoxOfficerResponseSchema.nullable().optional(),\n /** Resolution timestamp — surfaces the green resolution footer. */\n resolvedAt: z.string().datetime().nullable().optional(),\n\n score: z.number().int(),\n commentCount: z.number().int().nonnegative(),\n repostCount: z.number().int().nonnegative(),\n reactionCounts: z.record(z.string(), z.number().int().nonnegative()),\n\n createdAt: z.string().datetime(),\n\n viewer: z\n .object({\n vote: voteValueSchema.nullable(),\n reaction: z.string().nullable(),\n bookmarked: z.boolean(),\n isAuthor: z.boolean(),\n reposted: z.boolean(),\n })\n .optional(),\n});\nexport type VoiceBoxFeedItem = z.infer<typeof voiceBoxFeedItemSchema>;\n\n// ─── Polymorphic union ─────────────────────────────────────────────────────\n\nexport const feedItemSchema = z.discriminatedUnion('contentKind', [\n communityPostWireSchema,\n lostFoundFeedItemSchema,\n voiceBoxFeedItemSchema,\n donateItemFeedItemSchema,\n communityPollFeedItemSchema,\n crowdfundingFeedItemSchema,\n]);\nexport type FeedItem = z.infer<typeof feedItemSchema>;\n\n// ─── Query + response ──────────────────────────────────────────────────────\n\nexport const feedQueryParamsSchema = z.object({\n /** The viewer's chosen feed level. Cascade-upward semantics apply. */\n level: visibilityLevelSchema,\n /** Sort algorithm. Defaults to `hot` server-side when omitted. */\n sort: feedSortSchema.optional(),\n /** Opaque pagination cursor returned by the previous page. */\n cursor: z.string().optional(),\n /** Page size; defaults to `FEED_PAGE_SIZE` server-side. */\n pageSize: z.number().int().positive().max(50).optional(),\n});\nexport type FeedQueryParams = z.infer<typeof feedQueryParamsSchema>;\n\nexport const feedResponseSchema = z.object({\n items: z.array(feedItemSchema),\n nextCursor: z.string().nullable(),\n});\nexport type FeedResponse = z.infer<typeof feedResponseSchema>;\n\n// Re-export so consumers don't have to also import constants.ts.\nexport { FEED_PAGE_SIZE };\n"]}
1
+ {"version":3,"file":"feed.js","sourceRoot":"","sources":["../src/feed.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Feed wire shapes — polymorphic union of community posts, lost-and-\n * found reports, and voice-box (complaints + suggestions).\n *\n * The feed is a SINGLE list typed as `FeedItem = Post | LostFound | VoiceBox`.\n * The client discriminates on `contentKind` and renders the matching\n * card component.\n *\n * Strategy notes (server-side):\n * - Read-time fanout. The server runs ONE parallel query per kind\n * filtered by the same area-lineage match and the same cascade-\n * upward visibility rule, then merges and sorts by `hot` score.\n * - Cursor-based pagination. The cursor is opaque (base64 of\n * `<sortKey>|<_id>`) so we can swap sort algorithms without a\n * breaking change.\n * - LostFound / VoiceBox shapes are pruned to the fields the feed\n * card needs — they keep their richer detail-page shape in their\n * own schemas (lost-found-schema, voice-box-schema if/when those\n * get factored out).\n *\n * @module community-schema/feed\n */\n\nimport { z } from 'zod';\nimport { FEED_PAGE_SIZE } from './constants.js';\nimport { crowdfundingFeedItemSchema } from './crowdfunding.js';\nimport { voteValueSchema } from './engagement.js';\nimport { feedSortSchema, visibilityLevelSchema } from './enums.js';\nimport { communityPollFeedItemSchema } from './poll.js';\nimport { communityPostWireSchema, postAuthorSnapshotSchema } from './post.js';\n\n// ─── Per-kind feed envelopes ───────────────────────────────────────────────\n\n/**\n * Lost-and-found category enum — mirrors the reform-backend\n * `LOST_FOUND_CATEGORY` map. Stable English snake_case slugs; the\n * card maps each to an icon + localised label.\n */\nexport const LOST_FOUND_CATEGORY_VALUES = [\n 'electronics',\n 'jewelry',\n 'documents',\n 'clothing',\n 'pets',\n 'bags_luggage',\n 'keys',\n 'wallet_purse',\n 'phone',\n 'id_cards',\n 'other',\n] as const;\nexport const lostFoundCategorySchema = z.enum(LOST_FOUND_CATEGORY_VALUES);\nexport type LostFoundCategory = z.infer<typeof lostFoundCategorySchema>;\n\n/**\n * Lost-and-found status — `active` is the in-feed state, `resolved`\n * means a claim closed the report, `expired` means the auto-archive\n * window passed.\n */\nexport const LOST_FOUND_STATUS_VALUES = ['active', 'resolved', 'expired'] as const;\nexport const lostFoundStatusSchema = z.enum(LOST_FOUND_STATUS_VALUES);\nexport type LostFoundStatus = z.infer<typeof lostFoundStatusSchema>;\n\n/**\n * Slim area reference snapshot — mirrors the donations PickupAddress\n * AreaRefSnapshot. Stored on lost-found reports so the location pill\n * can show \"Locality, District, State\" without an Area lookup.\n */\nconst lostFoundAreaRefSchema = z.object({\n _id: z.string().optional(),\n name: z.string(),\n type: z.string().optional(),\n urbanBodyType: z.string().optional(),\n});\n\n/**\n * Structured location for a lost-found report. Mirrors the donations\n * pickup address with deliberate omissions: lost-found reports\n * describe an INCIDENT spot, not a delivery address, so\n * - `housePlotDetails` and `pincode` are dropped (no postal logistics);\n * - `coords` are dropped (no GPS capture — the reporter usually isn't\n * standing at the spot when they file the report);\n * - `landmark` + `directions` are kept (the user's free-text\n * description of where).\n *\n * Every field is optional so a sparse report (\"I lost it somewhere in\n * Mumbai\") is still valid.\n */\nexport const lostFoundLocationSchema = z.object({\n country: z.string().optional(),\n state: lostFoundAreaRefSchema.optional(),\n division: lostFoundAreaRefSchema.optional(),\n district: lostFoundAreaRefSchema.optional(),\n subDistrict: lostFoundAreaRefSchema.optional(),\n areaType: z.enum(['RURAL', 'URBAN']).optional(),\n block: lostFoundAreaRefSchema.optional(),\n gramPanchayat: lostFoundAreaRefSchema.optional(),\n village: lostFoundAreaRefSchema.optional(),\n hamlet: lostFoundAreaRefSchema.optional(),\n ruralWard: lostFoundAreaRefSchema.optional(),\n urbanBody: lostFoundAreaRefSchema.optional(),\n urbanWard: lostFoundAreaRefSchema.optional(),\n locality: lostFoundAreaRefSchema.optional(),\n policeStation: lostFoundAreaRefSchema.optional(),\n /** Free-text landmark, e.g. \"near the bus stop\". */\n landmark: z.string().max(200).optional(),\n /** Free-text additional context, e.g. \"south-west corner near the\n * parking lot\". Stored as `directions` on the model to match the\n * donations naming so the shared address normaliser works without\n * a per-feature aliasing layer. */\n directions: z.string().max(500).optional(),\n});\nexport type LostFoundLocation = z.infer<typeof lostFoundLocationSchema>;\n\n/** HH:MM-format time window on the report's date. Either endpoint may\n * be omitted, so the user can record \"after 2pm\", \"before 4pm\", or\n * \"between 2 and 4pm\" with the same shape. */\nexport const lostFoundTimeRangeSchema = z\n .object({\n startTime: z\n .string()\n .regex(/^([01]\\d|2[0-3]):[0-5]\\d$/, 'startTime must be HH:MM (24-hour)')\n .optional(),\n endTime: z\n .string()\n .regex(/^([01]\\d|2[0-3]):[0-5]\\d$/, 'endTime must be HH:MM (24-hour)')\n .optional(),\n })\n // At least one endpoint must be set — an empty `{}` adds no\n // information and is omitted by the form before submit.\n .refine((tr) => Boolean(tr.startTime || tr.endTime), {\n message: 'timeRange must include at least startTime or endTime',\n });\nexport type LostFoundTimeRange = z.infer<typeof lostFoundTimeRangeSchema>;\n\n/**\n * Lost-and-found item projected into the feed.\n *\n * v3 wire — extended to carry every field the production card renders\n * inline, so a single feed read serves the whole row. The detail page\n * (which loads `IReformLostFoundReport` directly) carries the long\n * tail of fields like `creatorName`, `resolvedWith`, audit logs.\n */\nexport const lostFoundFeedItemSchema = z.object({\n _id: z.string(),\n contentKind: z.literal('lost_found'),\n author: postAuthorSnapshotSchema,\n\n /** `'lost'` or `'found'` — drives the ribbon banner colour. */\n kind: z.enum(['lost', 'found']),\n title: z.string(),\n description: z.string(),\n\n // ─── v3 additions (all optional for backward compat) ─────────────\n // Live consumers reading the v1 wire keep working because every\n // new field is optional. The v3 projector populates them; the v3\n // card reads them. As consumers migrate to v3, the optionality can\n // tighten in a future minor bump.\n /** Curated category — drives the category icon + label chip.\n * Optional only until the v3 projector ships. */\n category: lostFoundCategorySchema.optional(),\n /** All images attached to the report (up to 5). The card renders a\n * swipeable carousel; the legacy `imageUrl` field below is kept\n * as a deprecated alias for `images[0]`. */\n images: z.array(z.string().url()).max(5).optional(),\n /** Where the item was lost / found.\n *\n * Structured shape: the area-hierarchy snapshot the user picked in\n * the LostFoundLocationDrawer plus optional `landmark` /\n * `directions` free-text. The card composes a single human-readable\n * string from these for the location pill.\n *\n * Backward compat: rows created before this migration carry a plain\n * string. The projector converts those legacy values to\n * `{ landmark: <string> }` on the way out so the wire always speaks\n * the new shape and the card stays simple. */\n location: lostFoundLocationSchema.optional(),\n /** Event date — when the item was lost / found. Distinct from\n * `createdAt`. */\n date: z.string().datetime().optional(),\n /** Optional time window on the report's `date` when the user\n * believes the item was lost or found. Both endpoints are HH:MM\n * strings (24-hour) and both are optional so the user can supply\n * just a start, just an end, or both. Omitted entirely when the\n * user couldn't narrow it down to a time. */\n timeRange: lostFoundTimeRangeSchema.optional(),\n /** For `kind === 'found'`: instructions on where to collect the\n * item. Null on `lost` reports. */\n collectionPoint: z.string().nullable().optional(),\n /** Public dial-back number captured on the report. */\n contactPhone: z.string().nullable().optional(),\n /** Lifecycle status. */\n status: lostFoundStatusSchema.optional(),\n /** Distinct-claimant count — drives the \"3 claims\" social-proof\n * chip. Maintained by the LostFoundClaim service. */\n claimCount: z.number().int().nonnegative().optional(),\n /** Free-text reward note (\"₹2,500\", \"Will treat to dinner\"). */\n rewardOffered: z.string().max(40).nullable().optional(),\n\n /** Deprecated single primary image. New consumers should read\n * `images[0]`; kept on the wire for the v1 card path. */\n imageUrl: z.string().url().optional(),\n\n /** Inherited engagement axis — same shape as posts. Score is the\n * signed net (upvotes - downvotes), can be negative. */\n score: z.number().int(),\n commentCount: z.number().int().nonnegative(),\n repostCount: z.number().int().nonnegative(),\n reactionCounts: z.record(z.string(), z.number().int().nonnegative()),\n\n createdAt: z.string().datetime(),\n\n viewer: z\n .object({\n vote: voteValueSchema.nullable(),\n reaction: z.string().nullable(),\n bookmarked: z.boolean(),\n isAuthor: z.boolean(),\n reposted: z.boolean(),\n })\n .optional(),\n});\nexport type LostFoundFeedItem = z.infer<typeof lostFoundFeedItemSchema>;\n\n/**\n * Donate-item status — mirrors the reform-backend\n * `ITEM_DONATION_STATUS` enum. `CANCELLED` is a terminal out-of-band\n * state (donor or admin withdrew the listing).\n */\nexport const DONATE_ITEM_STATUS_VALUES = [\n 'PENDING',\n 'VERIFIED',\n 'AT_CENTER',\n 'CANCELLED',\n 'DONATED',\n] as const;\nexport const donateItemStatusSchema = z.enum(DONATE_ITEM_STATUS_VALUES);\nexport type DonateItemStatus = z.infer<typeof donateItemStatusSchema>;\n\n/**\n * Item-condition labels surfaced on the chip. Mirrors the reform-\n * backend `ITEM_CONDITION` enum.\n */\nexport const DONATE_ITEM_CONDITION_VALUES = [\n 'NEW',\n 'LIKE_NEW',\n 'GOOD',\n 'FAIR',\n 'OLD_FUNCTIONAL',\n 'NEEDS_MINOR_REPAIR',\n 'NEEDS_MAJOR_REPAIR',\n 'FOR_PARTS',\n] as const;\nexport const donateItemConditionSchema = z.enum(DONATE_ITEM_CONDITION_VALUES);\nexport type DonateItemCondition = z.infer<typeof donateItemConditionSchema>;\n\n/** Audit summary shapes — short, denormalised projections of the\n * underlying pipeline blocks. The detail page carries the full\n * notes; the feed card just needs the \"who + when\". */\nexport const donateAuditByAtSchema = z.object({\n /** Display name of the person who performed the step. */\n byName: z.string(),\n /** When the step happened. */\n at: z.string().datetime(),\n});\nexport const donateAuditAtSchema = z.object({ at: z.string().datetime() });\nexport const donateDonatedToSchema = z.object({\n /** Name of the recipient (person or institution). */\n name: z.string(),\n at: z.string().datetime(),\n});\n\n/**\n * Donated-item listing projected into the feed.\n *\n * v3 wire — extended to carry every field the production card renders\n * inline. The full pickup-address sub-doc, verification notes, and\n * pipeline notes stay on the detail page.\n */\nexport const donateItemFeedItemSchema = z.object({\n _id: z.string(),\n contentKind: z.literal('donate_item'),\n /** Author of the donation. When `isAnonymous` is true, the wire\n * still ships a placeholder author (initials + neutral gradient,\n * no real `username` / `displayName`) — the server scrubs PII so\n * the wire is the privacy boundary, not the card. */\n author: postAuthorSnapshotSchema,\n\n /** Display name of the item. */\n itemName: z.string(),\n /** Optional free-text description. */\n description: z.string().optional(),\n /** Free-text category for now (the backend enum is widening; keeping\n * this open avoids a schema break each time a category is added). */\n category: z.string(),\n /** Item condition. Optional only because legacy rows pre-date the\n * field; new writes always populate it. */\n condition: donateItemConditionSchema.optional(),\n\n /** Lifecycle status — `string` for backward compat with v1\n * consumers that received an open string; v3 consumers should\n * refine against `donateItemStatusSchema`. */\n status: z.string(),\n\n // ─── v3 additions (all optional for backward compat) ─────────────\n /** Estimated worth in INR (₹). Null when the donor declined. */\n estimatedWorthInr: z.number().int().nullable().optional(),\n /** All photos attached to the donation (up to 3). */\n photos: z.array(z.string().url()).max(3).optional(),\n /** Donor opted to hide identity on the public feed. */\n isAnonymous: z.boolean().optional(),\n /** Distance from the viewer's `currentLocation` in km. */\n distanceKm: z.number().nonnegative().nullable().optional(),\n /** Date after which the donor is no longer available. */\n availableUntil: z.string().datetime().nullable().optional(),\n /** Pipeline audit summaries — each null when the step hasn't\n * happened yet. The card progressively reveals the blocks as the\n * donation moves through the pipeline. */\n verification: donateAuditByAtSchema.nullable().optional(),\n pickup: donateAuditByAtSchema.nullable().optional(),\n centerSubmission: donateAuditAtSchema.nullable().optional(),\n donatedTo: donateDonatedToSchema.nullable().optional(),\n\n /** Deprecated single primary image. New consumers should read\n * `photos[0]`; kept on the wire for the v1 card path. */\n imageUrl: z.string().url().optional(),\n\n score: z.number().int(),\n commentCount: z.number().int().nonnegative(),\n repostCount: z.number().int().nonnegative(),\n reactionCounts: z.record(z.string(), z.number().int().nonnegative()),\n\n createdAt: z.string().datetime(),\n\n viewer: z\n .object({\n vote: voteValueSchema.nullable(),\n reaction: z.string().nullable(),\n bookmarked: z.boolean(),\n isAuthor: z.boolean(),\n reposted: z.boolean(),\n })\n .optional(),\n});\nexport type DonateItemFeedItem = z.infer<typeof donateItemFeedItemSchema>;\n\n/**\n * Voice-box priority — mirrors `IReformIssueReport.priority`.\n * Drives the side-stripe colour on the complaint card.\n */\nexport const VOICE_BOX_PRIORITY_VALUES = ['low', 'medium', 'high', 'critical'] as const;\nexport const voiceBoxPrioritySchema = z.enum(VOICE_BOX_PRIORITY_VALUES);\nexport type VoiceBoxPriority = z.infer<typeof voiceBoxPrioritySchema>;\n\n/**\n * Voice-box lifecycle status. Five states matching the model — the\n * card surfaces `pending`/`under_review`/`in_progress` as in-flight\n * pills, `resolved` as a green resolution footer, `rejected` as\n * neutral with an explanation.\n */\nexport const VOICE_BOX_STATUS_VALUES = [\n 'pending',\n 'under_review',\n 'in_progress',\n 'resolved',\n 'rejected',\n] as const;\nexport const voiceBoxStatusSchema = z.enum(VOICE_BOX_STATUS_VALUES);\nexport type VoiceBoxStatus = z.infer<typeof voiceBoxStatusSchema>;\n\n/** Inline-playable audio attachment (voice complaint). The model\n * stores `IssueAudio` with `url + gcpPath + uploadedAt + duration`;\n * the wire is trimmed to what the card needs to render the WhatsApp-\n * style voice note bar. */\nexport const voiceBoxAudioSchema = z.object({\n url: z.string().url(),\n /** Duration in seconds. Drives the bar's duration chip. */\n durationSec: z.number().positive(),\n});\n\n/** Inline-playable video attachment (single native upload). */\nexport const voiceBoxVideoSchema = z.object({\n url: z.string().url(),\n thumbnailUrl: z.string().url(),\n durationSec: z.number().positive(),\n});\n\n/** Officer-response summary projected onto the feed wire so the card\n * can render the sky-blue \"Official response\" block without a\n * second round trip. Full text + reply audit log live on the\n * detail page. */\nexport const voiceBoxOfficerResponseSchema = z.object({\n /** Display name of the assigned officer. */\n officerName: z.string(),\n /** Officer's designation (Pradhan / Mayor / Junior Engineer / ...).\n * Null when the assigned user has no civic designation. */\n designation: z.string().nullable(),\n /** Truncated response text — max 280 chars. The full note lives on\n * the detail page. */\n text: z.string().max(280),\n respondedAt: z.string().datetime(),\n});\n\n/** Structured incident-location for a suggestion/complaint report.\n *\n * Same shape as `lostFoundLocationSchema` — area-hierarchy snapshot\n * the user picked in the location drawer (state / district /\n * locality / etc.) plus optional `landmark` + `directions` free-text.\n * Lat/lng intentionally NOT on the wire to keep reporter privacy\n * intact; the card composes a single human-readable string from\n * these via `formatLostFoundLocation` (the helper is shape-agnostic).\n *\n * Legacy rows authored before this migration carry a flat\n * `{ address, district, pinCode }` shape on the model; the feed\n * projector coerces those into `{ landmark: address, district:\n * { name: district } }` on the way out so consumers only see one\n * shape. */\nconst voiceBoxAreaRefSchema = z.object({\n _id: z.string().optional(),\n name: z.string(),\n type: z.string().optional(),\n urbanBodyType: z.string().optional(),\n});\n\nexport const voiceBoxLocationSchema = z.object({\n country: z.string().optional(),\n state: voiceBoxAreaRefSchema.optional(),\n division: voiceBoxAreaRefSchema.optional(),\n district: voiceBoxAreaRefSchema.optional(),\n subDistrict: voiceBoxAreaRefSchema.optional(),\n areaType: z.enum(['RURAL', 'URBAN']).optional(),\n block: voiceBoxAreaRefSchema.optional(),\n gramPanchayat: voiceBoxAreaRefSchema.optional(),\n village: voiceBoxAreaRefSchema.optional(),\n hamlet: voiceBoxAreaRefSchema.optional(),\n ruralWard: voiceBoxAreaRefSchema.optional(),\n urbanBody: voiceBoxAreaRefSchema.optional(),\n urbanWard: voiceBoxAreaRefSchema.optional(),\n locality: voiceBoxAreaRefSchema.optional(),\n policeStation: voiceBoxAreaRefSchema.optional(),\n landmark: z.string().max(200).optional(),\n directions: z.string().max(500).optional(),\n});\nexport type VoiceBoxLocation = z.infer<typeof voiceBoxLocationSchema>;\n\n/**\n * Voice-box (complaint or suggestion) item projected into the feed.\n *\n * v3 wire — extended from the v1 stub to carry every field the\n * civic-grade card renders. Privacy: `reporterPhone` is replaced by a\n * `hasReporterPhone` boolean so the public feed can show a Call CTA\n * without exposing the raw number; the detail page issues the\n * authenticated read that returns the actual tel: target.\n */\nexport const voiceBoxFeedItemSchema = z.object({\n _id: z.string(),\n contentKind: z.literal('voice_box'),\n author: postAuthorSnapshotSchema,\n\n /** `'complaint'` or `'suggestion'` — drives the card chrome (priority\n * stripe vs. Reddit-vote rail). */\n kind: z.enum(['complaint', 'suggestion']),\n title: z.string(),\n description: z.string(),\n\n // ─── v3 additions (all optional for backward compat) ─────────────\n // The v1 wire shipped only `kind / title / description`. The v3\n // card needs the full set; until the projector is upgraded the\n // fields here remain optional so production reads still validate.\n /** Free-text civic category (Water Supply / Electricity / ...). */\n category: z.string().optional(),\n /** Severity — drives the priority side stripe. */\n priority: voiceBoxPrioritySchema.optional(),\n /** Lifecycle status. */\n status: voiceBoxStatusSchema.optional(),\n\n /** Photo evidence — cap is 3 (matches the form policy). Legacy\n * rows authored before the cap was tightened may carry up to 10;\n * consumers should clamp at render time if they care. */\n images: z.array(z.string().url()).max(10).optional(),\n /** Voice-note attachment. */\n audio: voiceBoxAudioSchema.nullable().optional(),\n /** Single native video upload. */\n video: voiceBoxVideoSchema.nullable().optional(),\n /** External video links (YouTube / Vimeo). */\n videoLinks: z.array(z.string().url()).max(5).optional(),\n\n /** Address breakdown the card renders. */\n location: voiceBoxLocationSchema.optional(),\n\n /** Whether the report has a public-contact phone. The Call pill\n * links to a separate authenticated read that resolves the\n * number — keeping the raw phone out of the cached feed\n * response. */\n hasReporterPhone: z.boolean().optional(),\n\n /** Assigned-officer response summary. */\n officerResponse: voiceBoxOfficerResponseSchema.nullable().optional(),\n /** Resolution timestamp — surfaces the green resolution footer. */\n resolvedAt: z.string().datetime().nullable().optional(),\n\n score: z.number().int(),\n commentCount: z.number().int().nonnegative(),\n repostCount: z.number().int().nonnegative(),\n reactionCounts: z.record(z.string(), z.number().int().nonnegative()),\n\n createdAt: z.string().datetime(),\n\n viewer: z\n .object({\n vote: voteValueSchema.nullable(),\n reaction: z.string().nullable(),\n bookmarked: z.boolean(),\n isAuthor: z.boolean(),\n reposted: z.boolean(),\n })\n .optional(),\n});\nexport type VoiceBoxFeedItem = z.infer<typeof voiceBoxFeedItemSchema>;\n\n// ─── Polymorphic union ─────────────────────────────────────────────────────\n\nexport const feedItemSchema = z.discriminatedUnion('contentKind', [\n communityPostWireSchema,\n lostFoundFeedItemSchema,\n voiceBoxFeedItemSchema,\n donateItemFeedItemSchema,\n communityPollFeedItemSchema,\n crowdfundingFeedItemSchema,\n]);\nexport type FeedItem = z.infer<typeof feedItemSchema>;\n\n// ─── Query + response ──────────────────────────────────────────────────────\n\nexport const feedQueryParamsSchema = z.object({\n /** The viewer's chosen feed level. Cascade-upward semantics apply. */\n level: visibilityLevelSchema,\n /** Sort algorithm. Defaults to `hot` server-side when omitted. */\n sort: feedSortSchema.optional(),\n /** Opaque pagination cursor returned by the previous page. */\n cursor: z.string().optional(),\n /** Page size; defaults to `FEED_PAGE_SIZE` server-side. */\n pageSize: z.number().int().positive().max(50).optional(),\n});\nexport type FeedQueryParams = z.infer<typeof feedQueryParamsSchema>;\n\nexport const feedResponseSchema = z.object({\n items: z.array(feedItemSchema),\n nextCursor: z.string().nullable(),\n});\nexport type FeedResponse = z.infer<typeof feedResponseSchema>;\n\n// Re-export so consumers don't have to also import constants.ts.\nexport { FEED_PAGE_SIZE };\n"]}