refactor(cafes,cups): remove notes field from Cafe and Cup entities

- Add migrations 0014 and 0015 to drop notes columns
- Remove notes from domain structs, repositories, views, CLI, routes
- Remove notes textarea/columns from web templates
- Update bootstrap script, tests, backup module, and README
This commit is contained in:
Jon Seager 2026-02-03 21:09:34 +00:00
parent 23817ff95a
commit ae3c1090de
No known key found for this signature in database
11 changed files with 29 additions and 80 deletions

View file

@ -124,7 +124,7 @@ brewlog bag <cmd> Manage bags of coffee
brewlog gear <cmd> Manage brewing gear (grinders, brewers, filter papers) brewlog gear <cmd> Manage brewing gear (grinders, brewers, filter papers)
brewlog brew <cmd> Manage brews (add, list, get, delete — no update) brewlog brew <cmd> Manage brews (add, list, get, delete — no update)
brewlog cafe <cmd> Manage cafes brewlog cafe <cmd> Manage cafes
brewlog cup <cmd> Manage cups (tasting notes with ratings) brewlog cup <cmd> Manage cups (cafe visits with ratings)
brewlog token <cmd> Manage API tokens (create, list, revoke) brewlog token <cmd> Manage API tokens (create, list, revoke)
brewlog backup Export all data to JSON on stdout brewlog backup Export all data to JSON on stdout
brewlog restore --file F Restore data from a JSON backup into an empty database brewlog restore --file F Restore data from a JSON backup into an empty database

View file

@ -0,0 +1 @@
ALTER TABLE cups DROP COLUMN notes;

View file

@ -515,129 +515,128 @@ fi
./target/debug/brewlog cup add \ ./target/debug/brewlog cup add \
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Red Brick Espresso") | .id')" \ --roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Red Brick Espresso") | .id')" \
--cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Monmouth Coffee") | .id')" \ --cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Monmouth Coffee") | .id')" \
--notes "Rich and balanced; the house espresso blend is a crowd-pleaser." \
--rating 4 --rating 4
./target/debug/brewlog cup add \ ./target/debug/brewlog cup add \
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Kamwangi") | .id')" \ --roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Kamwangi") | .id')" \
--cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Monmouth Coffee") | .id')" \ --cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Monmouth Coffee") | .id')" \
--notes "Juicy Kenyan pour-over, bright blackcurrant notes." \
--rating 5 --rating 5
# Prufrock Coffee (London) - 3 cups # Prufrock Coffee (London) - 3 cups
./target/debug/brewlog cup add \ ./target/debug/brewlog cup add \
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Kochere") | .id')" \ --roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Kochere") | .id')" \
--cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Prufrock Coffee") | .id')" \ --cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Prufrock Coffee") | .id')" \
--notes "Delicate floral Ethiopian; exceptional barista technique." \
--rating 5 --rating 5
./target/debug/brewlog cup add \ ./target/debug/brewlog cup add \
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="La Laja") | .id')" \ --roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="La Laja") | .id')" \
--cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Prufrock Coffee") | .id')" \ --cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Prufrock Coffee") | .id')" \
--notes "Interesting Mexican natural, lots of chocolate." \
--rating 4 --rating 4
./target/debug/brewlog cup add \ ./target/debug/brewlog cup add \
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Ben Saïd Natural") | .id')" \ --roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Ben Saïd Natural") | .id')" \
--cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Prufrock Coffee") | .id')" \ --cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Prufrock Coffee") | .id')" \
--notes "Guest roast from Tim Wendelboe; bergamot hit was incredible." \
--rating 5 --rating 5
# Hola Coffee (Madrid) - 2 cups # Hola Coffee (Madrid) - 2 cups
./target/debug/brewlog cup add \ ./target/debug/brewlog cup add \
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Cerro Azul") | .id')" \ --roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Cerro Azul") | .id')" \
--cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Hola Coffee") | .id')" \ --cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Hola Coffee") | .id')" \
--notes "Clean Colombian washed, plum and grapefruit forward." \
--rating 4 --rating 4
./target/debug/brewlog cup add \ ./target/debug/brewlog cup add \
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Guji Highland") | .id')" \ --roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Guji Highland") | .id')" \
--cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Hola Coffee") | .id')" \ --cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Hola Coffee") | .id')" \
--notes "Peachy natural from April Coffee, worked well as espresso." \
--rating 3 --rating 3
# Toma Café (Madrid) - 1 cup # Toma Café (Madrid) - 1 cup
./target/debug/brewlog cup add \ ./target/debug/brewlog cup add \
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Daterra Sweet Collection") | .id')" \ --roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Daterra Sweet Collection") | .id')" \
--cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Toma Café") | .id')" \ --cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Toma Café") | .id')"
--notes "Smooth Brazilian, hazelnut and chocolate. Nice afternoon flat white."
# The Barn (Berlin) - 3 cups # The Barn (Berlin) - 3 cups
./target/debug/brewlog cup add \ ./target/debug/brewlog cup add \
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Gatomboya") | .id')" \ --roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Gatomboya") | .id')" \
--cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="The Barn") | .id')" \ --cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="The Barn") | .id')" \
--notes "Their own roast; classic Kenyan brightness with tomato acidity." \
--rating 4 --rating 4
./target/debug/brewlog cup add \ ./target/debug/brewlog cup add \
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Los Pirineos") | .id')" \ --roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Los Pirineos") | .id')" \
--cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="The Barn") | .id')" \ --cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="The Barn") | .id')" \
--notes "Honey-processed El Salvador, maple sweetness." \
--rating 4 --rating 4
./target/debug/brewlog cup add \ ./target/debug/brewlog cup add \
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Halo Beriti") | .id')" \ --roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Halo Beriti") | .id')" \
--cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="The Barn") | .id')" \ --cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="The Barn") | .id')" \
--notes "La Cabra guest roast, jasmine and lemon." \
--rating 5 --rating 5
# Companion Coffee (Berlin) - 2 cups # Companion Coffee (Berlin) - 2 cups
./target/debug/brewlog cup add \ ./target/debug/brewlog cup add \
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="El Paraiso 92 Anaerobic") | .id')" \ --roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="El Paraiso 92 Anaerobic") | .id')" \
--cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Companion Coffee") | .id')" \ --cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Companion Coffee") | .id')" \
--notes "Wild anaerobic from Dak; passionfruit explosion." \
--rating 5 --rating 5
./target/debug/brewlog cup add \ ./target/debug/brewlog cup add \
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Oreti SL28") | .id')" \ --roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Oreti SL28") | .id')" \
--cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Companion Coffee") | .id')" \ --cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Companion Coffee") | .id')" \
--notes "Crisp Kenyan SL28, grapefruit and plum." \
--rating 4 --rating 4
# Man Versus Machine (Munich) - 2 cups # Man Versus Machine (Munich) - 2 cups
./target/debug/brewlog cup add \ ./target/debug/brewlog cup add \
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Finca Tamana Washed") | .id')" \ --roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Finca Tamana Washed") | .id')" \
--cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Man Versus Machine") | .id')" \ --cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Man Versus Machine") | .id')" \
--notes "Clean Colombian, red apple and caramel. Beautiful V60." \
--rating 4 --rating 4
./target/debug/brewlog cup add \ ./target/debug/brewlog cup add \
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="La Esmeralda Geisha") | .id')" \ --roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="La Esmeralda Geisha") | .id')" \
--cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Man Versus Machine") | .id')" \ --cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Man Versus Machine") | .id')" \
--notes "Incredible Geisha from Friedhats; jasmine and papaya. Worth every penny." \
--rating 5 --rating 5
# Vits der Kaffee (Munich) - 1 cup # Vits der Kaffee (Munich) - 1 cup
./target/debug/brewlog cup add \ ./target/debug/brewlog cup add \
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="San Fermin") | .id')" \ --roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="San Fermin") | .id')" \
--cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Vits der Kaffee") | .id')" \ --cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Vits der Kaffee") | .id')" \
--notes "Origin Coffee guest roast; fruity Colombian, blood orange finish." \
--rating 3 --rating 3
# Full Court Press (Bristol) - 2 cups # Full Court Press (Bristol) - 2 cups
./target/debug/brewlog cup add \ ./target/debug/brewlog cup add \
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Suke Quto") | .id')" \ --roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Suke Quto") | .id')" \
--cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Full Court Press") | .id')" \ --cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Full Court Press") | .id')" \
--notes "Natural Ethiopian from Stow Coffee; blackberry and jasmine." \
--rating 5 --rating 5
./target/debug/brewlog cup add \ ./target/debug/brewlog cup add \
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Death to Decaf") | .id')" \ --roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Death to Decaf") | .id')" \
--cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Full Court Press") | .id')" \ --cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Full Court Press") | .id')" \
--notes "Surprisingly good decaf from Dark Arts. Cocoa and cherry." \
--rating 3 --rating 3
# Small Street Espresso (Bristol) - 2 cups # Small Street Espresso (Bristol) - 2 cups
./target/debug/brewlog cup add \ ./target/debug/brewlog cup add \
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Simbi") | .id')" \ --roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="Simbi") | .id')" \
--cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Small Street Espresso") | .id')" \ --cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Small Street Espresso") | .id')" \
--notes "Rwandan washed from Bows; clean black tea and orange." \
--rating 4 --rating 4
./target/debug/brewlog cup add \ ./target/debug/brewlog cup add \
--roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="La Chumeca") | .id')" \ --roast-id "$(./target/debug/brewlog roast list | jq -r '.[] | select(.name=="La Chumeca") | .id')" \
--cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Small Street Espresso") | .id')" \ --cafe-id "$(./target/debug/brewlog cafe list | jq -r '.[] | select(.name=="Small Street Espresso") | .id')" \
--notes "Costa Rican honey from Bows; sweet mandarin and honeycomb." \
--rating 4 --rating 4
# ============================================================================ # ============================================================================

View file

@ -142,7 +142,7 @@ pub(crate) async fn update_cup(
Path(id): Path<CupId>, Path(id): Path<CupId>,
Json(payload): Json<UpdateCup>, Json(payload): Json<UpdateCup>,
) -> Result<Json<Cup>, ApiError> { ) -> Result<Json<Cup>, ApiError> {
let has_changes = payload.notes.is_some() || payload.rating.is_some(); let has_changes = payload.rating.is_some();
if !has_changes { if !has_changes {
return Err(AppError::validation("no changes provided").into()); return Err(AppError::validation("no changes provided").into());

View file

@ -9,7 +9,6 @@ pub struct Cup {
pub id: CupId, pub id: CupId,
pub roast_id: RoastId, pub roast_id: RoastId,
pub cafe_id: CafeId, pub cafe_id: CafeId,
pub notes: Option<String>,
pub rating: Option<i32>, pub rating: Option<i32>,
pub created_at: DateTime<Utc>, pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>, pub updated_at: DateTime<Utc>,
@ -31,13 +30,11 @@ pub struct CupWithDetails {
pub struct NewCup { pub struct NewCup {
pub roast_id: RoastId, pub roast_id: RoastId,
pub cafe_id: CafeId, pub cafe_id: CafeId,
pub notes: Option<String>,
pub rating: Option<i32>, pub rating: Option<i32>,
} }
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct UpdateCup { pub struct UpdateCup {
pub notes: Option<String>,
pub rating: Option<i32>, pub rating: Option<i32>,
} }

View file

@ -13,7 +13,7 @@ use crate::infrastructure::database::DatabasePool;
const BASE_SELECT: &str = r" const BASE_SELECT: &str = r"
SELECT SELECT
c.id, c.roast_id, c.cafe_id, c.notes, c.rating, c.id, c.roast_id, c.cafe_id, c.rating,
c.created_at, c.updated_at, c.created_at, c.updated_at,
r.name as roast_name, r.slug as roast_slug, r.name as roast_name, r.slug as roast_slug,
rr.name as roaster_name, rr.slug as roaster_slug, rr.name as roaster_name, rr.slug as roaster_slug,
@ -57,7 +57,6 @@ impl SqlCupRepository {
id: CupId::new(record.id), id: CupId::new(record.id),
roast_id: RoastId::new(record.roast_id), roast_id: RoastId::new(record.roast_id),
cafe_id: CafeId::new(record.cafe_id), cafe_id: CafeId::new(record.cafe_id),
notes: record.notes,
rating: record.rating, rating: record.rating,
created_at: record.created_at, created_at: record.created_at,
updated_at: record.updated_at, updated_at: record.updated_at,
@ -70,7 +69,6 @@ impl SqlCupRepository {
id: CupId::new(record.id), id: CupId::new(record.id),
roast_id: RoastId::new(record.roast_id), roast_id: RoastId::new(record.roast_id),
cafe_id: CafeId::new(record.cafe_id), cafe_id: CafeId::new(record.cafe_id),
notes: record.notes,
rating: record.rating, rating: record.rating,
created_at: record.created_at, created_at: record.created_at,
updated_at: record.updated_at, updated_at: record.updated_at,
@ -141,12 +139,11 @@ impl CupRepository for SqlCupRepository {
.map_err(|err| RepositoryError::unexpected(err.to_string()))?; .map_err(|err| RepositoryError::unexpected(err.to_string()))?;
let record = query_as::<_, CupRecord>( let record = query_as::<_, CupRecord>(
"INSERT INTO cups (roast_id, cafe_id, notes, rating) VALUES (?, ?, ?, ?) \ "INSERT INTO cups (roast_id, cafe_id, rating) VALUES (?, ?, ?) \
RETURNING id, roast_id, cafe_id, notes, rating, created_at, updated_at", RETURNING id, roast_id, cafe_id, rating, created_at, updated_at",
) )
.bind(new_cup.roast_id.into_inner()) .bind(new_cup.roast_id.into_inner())
.bind(new_cup.cafe_id.into_inner()) .bind(new_cup.cafe_id.into_inner())
.bind(new_cup.notes.as_deref())
.bind(new_cup.rating) .bind(new_cup.rating)
.fetch_one(&mut *tx) .fetch_one(&mut *tx)
.await .await
@ -196,7 +193,7 @@ impl CupRepository for SqlCupRepository {
async fn get(&self, id: CupId) -> Result<Cup, RepositoryError> { async fn get(&self, id: CupId) -> Result<Cup, RepositoryError> {
let record = query_as::<_, CupRecord>( let record = query_as::<_, CupRecord>(
"SELECT id, roast_id, cafe_id, notes, rating, created_at, updated_at FROM cups WHERE id = ?", "SELECT id, roast_id, cafe_id, rating, created_at, updated_at FROM cups WHERE id = ?",
) )
.bind(i64::from(id)) .bind(i64::from(id))
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
@ -268,7 +265,6 @@ impl CupRepository for SqlCupRepository {
let mut builder = QueryBuilder::new("UPDATE cups SET updated_at = CURRENT_TIMESTAMP"); let mut builder = QueryBuilder::new("UPDATE cups SET updated_at = CURRENT_TIMESTAMP");
let mut sep = true; let mut sep = true;
push_update_field!(builder, sep, "notes", changes.notes);
push_update_field!(builder, sep, "rating", changes.rating); push_update_field!(builder, sep, "rating", changes.rating);
let _ = sep; let _ = sep;
@ -308,7 +304,6 @@ struct CupRecord {
id: i64, id: i64,
roast_id: i64, roast_id: i64,
cafe_id: i64, cafe_id: i64,
notes: Option<String>,
rating: Option<i32>, rating: Option<i32>,
created_at: DateTime<Utc>, created_at: DateTime<Utc>,
updated_at: DateTime<Utc>, updated_at: DateTime<Utc>,
@ -319,7 +314,6 @@ struct CupWithDetailsRecord {
id: i64, id: i64,
roast_id: i64, roast_id: i64,
cafe_id: i64, cafe_id: i64,
notes: Option<String>,
rating: Option<i32>, rating: Option<i32>,
created_at: DateTime<Utc>, created_at: DateTime<Utc>,
updated_at: DateTime<Utc>, updated_at: DateTime<Utc>,

View file

@ -38,8 +38,6 @@ pub struct AddCupCommand {
#[arg(long)] #[arg(long)]
pub cafe_id: i64, pub cafe_id: i64,
#[arg(long)] #[arg(long)]
pub notes: Option<String>,
#[arg(long)]
pub rating: Option<i32>, pub rating: Option<i32>,
} }
@ -47,7 +45,6 @@ pub async fn add_cup(client: &BrewlogClient, command: AddCupCommand) -> Result<(
let payload = NewCup { let payload = NewCup {
roast_id: RoastId::new(command.roast_id), roast_id: RoastId::new(command.roast_id),
cafe_id: CafeId::new(command.cafe_id), cafe_id: CafeId::new(command.cafe_id),
notes: command.notes,
rating: command.rating, rating: command.rating,
}; };
@ -67,14 +64,11 @@ pub struct UpdateCupCommand {
#[arg(long)] #[arg(long)]
pub id: i64, pub id: i64,
#[arg(long)] #[arg(long)]
pub notes: Option<String>,
#[arg(long)]
pub rating: Option<i32>, pub rating: Option<i32>,
} }
pub async fn update_cup(client: &BrewlogClient, command: UpdateCupCommand) -> Result<()> { pub async fn update_cup(client: &BrewlogClient, command: UpdateCupCommand) -> Result<()> {
let payload = UpdateCup { let payload = UpdateCup {
notes: command.notes,
rating: command.rating, rating: command.rating,
}; };

View file

@ -9,8 +9,6 @@ pub struct CupView {
pub roaster_slug: String, pub roaster_slug: String,
pub cafe_name: String, pub cafe_name: String,
pub cafe_slug: String, pub cafe_slug: String,
pub notes: String,
pub has_notes: bool,
pub rating: String, pub rating: String,
pub has_rating: bool, pub has_rating: bool,
pub created_at: String, pub created_at: String,
@ -18,8 +16,6 @@ pub struct CupView {
impl CupView { impl CupView {
pub fn from_domain(cup: CupWithDetails) -> Self { pub fn from_domain(cup: CupWithDetails) -> Self {
let notes = cup.cup.notes.clone().unwrap_or_default();
let has_notes = !notes.is_empty();
let rating = cup let rating = cup
.cup .cup
.rating .rating
@ -34,8 +30,6 @@ impl CupView {
roaster_slug: cup.roaster_slug, roaster_slug: cup.roaster_slug,
cafe_name: cup.cafe_name, cafe_name: cup.cafe_name,
cafe_slug: cup.cafe_slug, cafe_slug: cup.cafe_slug,
notes,
has_notes,
rating, rating,
has_rating, has_rating,
created_at: cup.cup.created_at.format("%Y-%m-%d %H:%M").to_string(), created_at: cup.cup.created_at.format("%Y-%m-%d %H:%M").to_string(),

View file

@ -70,15 +70,6 @@
<option value="1">1 - Poor</option> <option value="1">1 - Poor</option>
</select> </select>
</label> </label>
<label class="sm:col-span-2 flex flex-col gap-1 text-sm">
<span class="text-stone-700">Notes</span>
<textarea
name="notes"
rows="2"
class="input-field"
placeholder="Tasting impressions, preparation style..."
></textarea>
</label>
</div> </div>
<div class="flex items-center justify-end gap-2"> <div class="flex items-center justify-end gap-2">
<button <button

View file

@ -22,7 +22,6 @@
{% call table::sortable_header("Coffee", "roast", navigator, "#cup-list") %} {% call table::sortable_header("Coffee", "roast", navigator, "#cup-list") %}
{% call table::sortable_header("Cafe", "cafe", navigator, "#cup-list") %} {% call table::sortable_header("Cafe", "cafe", navigator, "#cup-list") %}
{% call table::sortable_header("Rating", "rating", navigator, "#cup-list") %} {% call table::sortable_header("Rating", "rating", navigator, "#cup-list") %}
<th scope="col" class="mobile-hidden px-4 py-3">Notes</th>
<th scope="col" class="px-4 py-3 text-right">Actions</th> <th scope="col" class="px-4 py-3 text-right">Actions</th>
</tr> </tr>
</thead> </thead>
@ -52,9 +51,6 @@
> >
</td> </td>
<td data-label="Rating" class="px-4 py-3 whitespace-nowrap">{{ cup.rating }}</td> <td data-label="Rating" class="px-4 py-3 whitespace-nowrap">{{ cup.rating }}</td>
<td data-label="Notes" class="mobile-hidden px-4 py-3 text-sm text-stone-600">
{% if cup.has_notes %}{{ cup.notes }}{% else %}&mdash;{% endif %}
</td>
<td data-label="" class="px-4 py-3 text-right"> <td data-label="" class="px-4 py-3 text-right">
{% if is_authenticated %} {% if is_authenticated %}
<div class="inline-flex items-center gap-1"> <div class="inline-flex items-center gap-1">

View file

@ -16,7 +16,6 @@ async fn creating_a_cup_returns_a_201_for_valid_data() {
let new_cup = NewCup { let new_cup = NewCup {
roast_id: roast.id, roast_id: roast.id,
cafe_id: cafe.id, cafe_id: cafe.id,
notes: Some("Excellent pour-over".to_string()),
rating: Some(5), rating: Some(5),
}; };
@ -33,7 +32,6 @@ async fn creating_a_cup_returns_a_201_for_valid_data() {
let cup: Cup = response.json().await.expect("Failed to parse response"); let cup: Cup = response.json().await.expect("Failed to parse response");
assert_eq!(cup.roast_id, roast.id); assert_eq!(cup.roast_id, roast.id);
assert_eq!(cup.cafe_id, cafe.id); assert_eq!(cup.cafe_id, cafe.id);
assert_eq!(cup.notes, Some("Excellent pour-over".to_string()));
assert_eq!(cup.rating, Some(5)); assert_eq!(cup.rating, Some(5));
} }
@ -49,7 +47,6 @@ async fn creating_a_cup_without_optional_fields_returns_a_201() {
let new_cup = NewCup { let new_cup = NewCup {
roast_id: roast.id, roast_id: roast.id,
cafe_id: cafe.id, cafe_id: cafe.id,
notes: None,
rating: None, rating: None,
}; };
@ -64,7 +61,6 @@ async fn creating_a_cup_without_optional_fields_returns_a_201() {
assert_eq!(response.status(), 201); assert_eq!(response.status(), 201);
let cup: Cup = response.json().await.expect("Failed to parse response"); let cup: Cup = response.json().await.expect("Failed to parse response");
assert_eq!(cup.notes, None);
assert_eq!(cup.rating, None); assert_eq!(cup.rating, None);
} }
@ -76,7 +72,6 @@ async fn creating_a_cup_requires_authentication() {
let new_cup = NewCup { let new_cup = NewCup {
roast_id: RoastId::new(1), roast_id: RoastId::new(1),
cafe_id: CafeId::new(1), cafe_id: CafeId::new(1),
notes: None,
rating: None, rating: None,
}; };
@ -119,7 +114,6 @@ async fn listing_cups_returns_a_200_with_enriched_data() {
let new_cup = NewCup { let new_cup = NewCup {
roast_id: roast.id, roast_id: roast.id,
cafe_id: cafe.id, cafe_id: cafe.id,
notes: None,
rating: Some(4), rating: Some(4),
}; };
@ -158,7 +152,6 @@ async fn getting_a_cup_returns_a_200_with_details() {
let new_cup = NewCup { let new_cup = NewCup {
roast_id: roast.id, roast_id: roast.id,
cafe_id: cafe.id, cafe_id: cafe.id,
notes: Some("Great".to_string()),
rating: Some(3), rating: Some(3),
}; };
@ -215,7 +208,6 @@ async fn updating_a_cup_returns_a_200_for_valid_data() {
let new_cup = NewCup { let new_cup = NewCup {
roast_id: roast.id, roast_id: roast.id,
cafe_id: cafe.id, cafe_id: cafe.id,
notes: None,
rating: None, rating: None,
}; };
@ -232,10 +224,7 @@ async fn updating_a_cup_returns_a_200_for_valid_data() {
.await .await
.expect("Failed to parse response"); .expect("Failed to parse response");
let update = UpdateCup { let update = UpdateCup { rating: Some(4) };
notes: Some("Updated notes".to_string()),
rating: Some(4),
};
let response = client let response = client
.put(app.api_url(&format!("/cups/{}", cup.id))) .put(app.api_url(&format!("/cups/{}", cup.id)))
@ -248,7 +237,6 @@ async fn updating_a_cup_returns_a_200_for_valid_data() {
assert_eq!(response.status(), 200); assert_eq!(response.status(), 200);
let updated: Cup = response.json().await.expect("Failed to parse response"); let updated: Cup = response.json().await.expect("Failed to parse response");
assert_eq!(updated.notes, Some("Updated notes".to_string()));
assert_eq!(updated.rating, Some(4)); assert_eq!(updated.rating, Some(4));
} }
@ -264,7 +252,6 @@ async fn updating_a_cup_with_no_changes_returns_a_400() {
let new_cup = NewCup { let new_cup = NewCup {
roast_id: roast.id, roast_id: roast.id,
cafe_id: cafe.id, cafe_id: cafe.id,
notes: None,
rating: None, rating: None,
}; };
@ -281,10 +268,7 @@ async fn updating_a_cup_with_no_changes_returns_a_400() {
.await .await
.expect("Failed to parse response"); .expect("Failed to parse response");
let update = UpdateCup { let update = UpdateCup { rating: None };
notes: None,
rating: None,
};
let response = client let response = client
.put(app.api_url(&format!("/cups/{}", cup.id))) .put(app.api_url(&format!("/cups/{}", cup.id)))
@ -309,7 +293,6 @@ async fn deleting_a_cup_returns_a_204_for_valid_id() {
let new_cup = NewCup { let new_cup = NewCup {
roast_id: roast.id, roast_id: roast.id,
cafe_id: cafe.id, cafe_id: cafe.id,
notes: None,
rating: None, rating: None,
}; };