Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions docs/developer-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ Required query parameter: `q` (2–200 characters). Optional `limit` defaults to

Downloads one shared, lightweight snapshot of every published gear record. It is
slug-sorted and contains only `name`, `slug`, `brandName`, `gearType`,
`thumbnailUrl`, `releaseDate`, `releaseDatePrecision`, `announcedDate`, and
`announceDatePrecision` for each item. It deliberately excludes specifications,
`thumbnailUrl`, `releaseDate`, `releaseDatePrecision`, `announcedDate`,
`announceDatePrecision`, `discontinuedDate`, and `discontinuedDatePrecision`
for each item. It deliberately excludes specifications,
aliases, samples, colourways, prices, IDs, and audit metadata.

```json
Expand Down
2 changes: 1 addition & 1 deletion docs/gear-editing/auto-approvals.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ Publication state and completeness are separate:

- For each included key under `core`, `camera`, `analogCamera`, `lens`, and `fixedLens`, the **current** value on the gear must be “empty” and the **proposed** value must be non-empty (no overwrites, no clearing), except registered overwrite allowlist entries.
- Same idea for top-level **`cameraCardSlots`** and **`videoModes`**: only allowed when the current value is empty and the proposal fills them.
- The current overwrite allowlist permits non-empty replacements of `core.releaseDatePrecision` and `core.announceDatePrecision`; clearing either field or replacing any other populated value still requires review.
- The current overwrite allowlist permits non-empty replacements of `core.releaseDatePrecision`, `core.announceDatePrecision`, and `core.discontinuedDatePrecision`; clearing any of those fields or replacing any other populated value still requires review.

**Slug:** Eligibility loads the full gear row by **`gearMeta.slug`**; if slug is missing, trusted eligibility is false.

Expand Down
2 changes: 1 addition & 1 deletion docs/gear-specification-system.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ CREATE TABLE sharply_gear (
-- Primary key and identifiers
-- Basic information (name, slug, search name)
-- Classification (gear type, brand, mount)
-- Metadata (release date, price, thumbnail, top/rear secondary images)
-- Metadata (announced/release/discontinued dates + precision, price, thumbnail, top/rear secondary images)
-- Timestamps
);

Expand Down
2 changes: 1 addition & 1 deletion docs/spec-editing-flow-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ type ComponentName = keyof typeof SPEC_INPUT_COMPONENTS;
- **Notes**: Optional explanation of why changes are needed
- **Role-Aware Submit**:
- Editors/Admins: If there are no existing change requests, their submission applies immediately—no review queue, preventing stale merges
- Trusted contributors: If they have at least one approved spec edit, there are no existing change requests, and the proposal is strictly add-only (fills empty values without overwriting or clearing existing data), the submission applies immediately regardless of gear completeness or publication state. The only registered overwrite exceptions are non-empty replacements of `releaseDatePrecision` and `announceDatePrecision`; clearing either precision, or changing either date value, still requires review.
- Trusted contributors: If they have at least one approved spec edit, there are no existing change requests, and the proposal is strictly add-only (fills empty values without overwriting or clearing existing data), the submission applies immediately regardless of gear completeness or publication state. The only registered overwrite exceptions are non-empty replacements of `releaseDatePrecision`, `announceDatePrecision`, and `discontinuedDatePrecision`; clearing any of those precisions, or changing any of the paired date values, still requires review.
- Everyone else (or staff when another request is open, or trusted contributors whose proposal is not add-only): Submission enters the proposal queue (`status: PENDING`) for review
- **Publication-state awareness**:
- Rumored and hidden items still keep the internal edit flow available to staff so content can be prepared before publication.
Expand Down
4 changes: 4 additions & 0 deletions messages/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,7 @@
"fields": {
"announcedDatePrecision": "Präzision des Ankündigungsdatums",
"releaseDatePrecision": "Präzision des Veröffentlichungsdatums",
"discontinuedDatePrecision": "Präzision des Einstellungsdatums",
"datePrecisionHelp": "Wähle eine Genauigkeitsstufe für das Datum. Wenn du zum Beispiel „Monat“ auswählst, wird das Datum als „September 2025“ statt „5. September 2025“ angezeigt. Mit „Jahr“ wird nur das Jahr gezeigt. Verwende „Tag“, wenn das vollständige Datum bekannt ist.",
"datePrecisionYear": "Jahr",
"datePrecisionMonth": "Monat",
Expand Down Expand Up @@ -757,6 +758,9 @@
"releaseDate": {
"label": "Veröffentlichungsdatum"
},
"discontinuedDate": {
"label": "Einstellungsdatum"
},
"msrpAtLaunchUsdCents": {
"label": "UVP zum Marktstart"
},
Expand Down
4 changes: 4 additions & 0 deletions messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,7 @@
"aperture": "Aperture",
"announcedDatePrecision": "Announced Date Precision",
"releaseDatePrecision": "Release Date Precision",
"discontinuedDatePrecision": "Discontinued Date Precision",
"datePrecisionHelp": "Select a precision level for the date. For example, selecting \"Month\" will display the date as \"September 2025\" instead of \"September 5, 2025\". Selecting \"Year\" will only show the year. Use \"Day\" when the full date is known.",
"datePrecisionYear": "Year",
"datePrecisionMonth": "Month",
Expand Down Expand Up @@ -757,6 +758,9 @@
"releaseDate": {
"label": "Release Date"
},
"discontinuedDate": {
"label": "Discontinued Date"
},
"msrpAtLaunchUsdCents": {
"label": "MSRP At Launch"
},
Expand Down
4 changes: 4 additions & 0 deletions messages/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,7 @@
"fields": {
"announcedDatePrecision": "Precisión de la fecha de anuncio",
"releaseDatePrecision": "Precisión de la fecha de lanzamiento",
"discontinuedDatePrecision": "Precisión de la fecha de discontinuación",
"datePrecisionHelp": "Selecciona un nivel de precisión para la fecha. Por ejemplo, al elegir \"Mes\" la fecha se mostrará como \"septiembre de 2025\" en lugar de \"5 de septiembre de 2025\". Al elegir \"Año\" solo se mostrará el año. Usa \"Día\" cuando se conozca la fecha completa.",
"datePrecisionYear": "Año",
"datePrecisionMonth": "Mes",
Expand Down Expand Up @@ -757,6 +758,9 @@
"releaseDate": {
"label": "Fecha de lanzamiento"
},
"discontinuedDate": {
"label": "Fecha de discontinuación"
},
"msrpAtLaunchUsdCents": {
"label": "PVP de lanzamiento"
},
Expand Down
4 changes: 4 additions & 0 deletions messages/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,7 @@
"fields": {
"announcedDatePrecision": "Précision de la date d’annonce",
"releaseDatePrecision": "Précision de la date de sortie",
"discontinuedDatePrecision": "Précision de la date de fin de commercialisation",
"datePrecisionHelp": "Choisissez un niveau de précision pour la date. Par exemple, sélectionner « Mois » affichera la date comme « septembre 2025 » au lieu de « 5 septembre 2025 ». « Année » n’affichera que l’année. Utilisez « Jour » lorsque la date complète est connue.",
"datePrecisionYear": "Année",
"datePrecisionMonth": "Mois",
Expand Down Expand Up @@ -757,6 +758,9 @@
"releaseDate": {
"label": "Date de sortie"
},
"discontinuedDate": {
"label": "Date de fin de commercialisation"
},
"msrpAtLaunchUsdCents": {
"label": "Prix de lancement conseillé"
},
Expand Down
4 changes: 4 additions & 0 deletions messages/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,7 @@
"fields": {
"announcedDatePrecision": "Precisione della data di annuncio",
"releaseDatePrecision": "Precisione della data di uscita",
"discontinuedDatePrecision": "Precisione della data di dismissione",
"datePrecisionHelp": "Seleziona un livello di precisione per la data. Ad esempio, scegliendo \"Mese\" la data sarà mostrata come \"settembre 2025\" invece di \"5 settembre 2025\". Scegliendo \"Anno\" verrà mostrato solo l’anno. Usa \"Giorno\" quando è disponibile la data completa.",
"datePrecisionYear": "Anno",
"datePrecisionMonth": "Mese",
Expand Down Expand Up @@ -757,6 +758,9 @@
"releaseDate": {
"label": "Data di uscita"
},
"discontinuedDate": {
"label": "Data di dismissione"
},
"msrpAtLaunchUsdCents": {
"label": "Prezzo di listino al lancio"
},
Expand Down
4 changes: 4 additions & 0 deletions messages/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,7 @@
"fields": {
"announcedDatePrecision": "発表日の精度",
"releaseDatePrecision": "発売日の精度",
"discontinuedDatePrecision": "販売終了日の精度",
"datePrecisionHelp": "日付の精度レベルを選択してください。たとえば「月」を選ぶと、日付は「2025年9月」のように表示され、「2025年9月5日」では表示されません。「年」を選ぶと年のみ表示されます。完全な日付が分かっている場合は「日」を使ってください。",
"datePrecisionYear": "年",
"datePrecisionMonth": "月",
Expand Down Expand Up @@ -757,6 +758,9 @@
"releaseDate": {
"label": "発売日"
},
"discontinuedDate": {
"label": "販売終了日"
},
"msrpAtLaunchUsdCents": {
"label": "発売時希望小売価格"
},
Expand Down
4 changes: 4 additions & 0 deletions messages/ms.json
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,7 @@
"fields": {
"announcedDatePrecision": "Ketepatan tarikh pengumuman",
"releaseDatePrecision": "Ketepatan tarikh keluaran",
"discontinuedDatePrecision": "Ketepatan tarikh dihentikan",
"datePrecisionHelp": "Pilih tahap ketepatan untuk tarikh. Contohnya, memilih \"Bulan\" akan memaparkan tarikh sebagai \"September 2025\" dan bukannya \"5 September 2025\". Memilih \"Tahun\" hanya akan memaparkan tahun. Gunakan \"Hari\" apabila tarikh penuh diketahui.",
"datePrecisionYear": "Tahun",
"datePrecisionMonth": "Bulan",
Expand Down Expand Up @@ -757,6 +758,9 @@
"releaseDate": {
"label": "Tarikh pelancaran"
},
"discontinuedDate": {
"label": "Tarikh dihentikan"
},
"msrpAtLaunchUsdCents": {
"label": "MSRP semasa pelancaran"
},
Expand Down
4 changes: 4 additions & 0 deletions messages/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,7 @@
"aperture": "光圈",
"announcedDatePrecision": "公布的日期精度",
"releaseDatePrecision": "发布日期精度",
"discontinuedDatePrecision": "停产日期精度",
"datePrecisionHelp": "选择日期的精度级别。例如,选择“月”会将日期显示为“2025 年 9 月”,而不是“2025 年 9 月 5 日”。选择“年份”将仅显示年份。当完整日期已知时,使用“日”。",
"datePrecisionYear": "年",
"datePrecisionMonth": "月",
Expand Down Expand Up @@ -757,6 +758,9 @@
"releaseDate": {
"label": "发布日期"
},
"discontinuedDate": {
"label": "停产日期"
},
"msrpAtLaunchUsdCents": {
"label": "发布时的建议零售价"
},
Expand Down
14 changes: 12 additions & 2 deletions src/app/[locale]/(admin)/admin/gear-proposals-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,12 @@ export function GearProposalsList() {
k === "msrpAtLaunchUsdCents"
)
return formatPrice(v as number);
if (k === "releaseDate") return formatDisplayDate(v);
if (
k === "releaseDate" ||
k === "announcedDate" ||
k === "discontinuedDate"
)
return formatDisplayDate(v);
if (k === "sensorFormatId") return sensorNameFromSlug(v as string);
if (k === "mountId") return getMountLongNameById(v as string);
if (k === "mountIds") {
Expand All @@ -237,7 +242,12 @@ export function GearProposalsList() {
k === "msrpAtLaunchUsdCents"
)
return formatPrice(v as number);
if (k === "releaseDate") return formatDisplayDate(v);
if (
k === "releaseDate" ||
k === "announcedDate" ||
k === "discontinuedDate"
)
return formatDisplayDate(v);
if (k === "sensorFormatId") return sensorNameFromId(v as string);
if (k === "mountId") return getMountLongNameById(v as string);
if (k === "mountIds") {
Expand Down
6 changes: 5 additions & 1 deletion src/app/[locale]/(pages)/edit-success/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,11 @@ export default async function EditSuccessPage({
k === "msrpAtLaunchUsdCents"
)
display = formatPrice(v as number);
if (k === "releaseDate")
if (
k === "releaseDate" ||
k === "announcedDate" ||
k === "discontinuedDate"
)
display = formatDate(v as any, {
locale,
preset: "date-long",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,18 @@ function EditGearForm({
return getSpecFieldLabel(t, "core", "releaseDate", "Release Date");
case "releaseDatePrecision":
return tf("editGear.fields.releaseDatePrecision", "Release Date Precision");
case "discontinuedDate":
return getSpecFieldLabel(
t,
"core",
"discontinuedDate",
"Discontinued Date",
);
case "discontinuedDatePrecision":
return tf(
"editGear.fields.discontinuedDatePrecision",
"Discontinued Date Precision",
);
case "msrpNowUsdCents":
return tf("editGear.fields.msrpNow", "MSRP now (USD)");
case "msrpAtLaunchUsdCents":
Expand Down Expand Up @@ -598,6 +610,8 @@ function EditGearForm({
"announceDatePrecision",
"releaseDate",
"releaseDatePrecision",
"discontinuedDate",
"discontinuedDatePrecision",
"msrpNowUsdCents",
"msrpAtLaunchUsdCents",
"mpbMaxPriceUsdCents",
Expand Down Expand Up @@ -1106,6 +1120,8 @@ function EditGearForm({
announceDatePrecision: formData.announceDatePrecision,
releaseDate: formData.releaseDate ?? null,
releaseDatePrecision: formData.releaseDatePrecision,
discontinuedDate: formData.discontinuedDate ?? null,
discontinuedDatePrecision: formData.discontinuedDatePrecision,
msrpNowUsdCents: formData.msrpNowUsdCents ?? null,
msrpAtLaunchUsdCents: formData.msrpAtLaunchUsdCents ?? null,
mpbMaxPriceUsdCents: formData.mpbMaxPriceUsdCents ?? null,
Expand All @@ -1128,6 +1144,9 @@ function EditGearForm({
announceDatePrecision: initialCoreSpecs.announceDatePrecision,
releaseDate: initialCoreSpecs.releaseDate ?? null,
releaseDatePrecision: initialCoreSpecs.releaseDatePrecision,
discontinuedDate: initialCoreSpecs.discontinuedDate ?? null,
discontinuedDatePrecision:
initialCoreSpecs.discontinuedDatePrecision,
msrpNowUsdCents: initialCoreSpecs.msrpNowUsdCents ?? null,
msrpAtLaunchUsdCents: initialCoreSpecs.msrpAtLaunchUsdCents ?? null,
mpbMaxPriceUsdCents: initialCoreSpecs.mpbMaxPriceUsdCents ?? null,
Expand Down Expand Up @@ -1309,7 +1328,9 @@ function EditGearForm({
)
display = formatPrice(normalizePriceCents(v));
if (
(k === "releaseDate" || k === "announcedDate") &&
(k === "releaseDate" ||
k === "announcedDate" ||
k === "discontinuedDate") &&
(typeof v === "string" || v instanceof Date)
)
display = formatDate(v, {
Expand Down
Loading
Loading