Compare commits
5 commits
939668c4fb
...
2ea386e557
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ea386e557 | ||
|
|
820d31b3e5 | ||
|
|
ae1263acff | ||
|
|
fe52089c38 | ||
|
|
411b738c2f |
13 changed files with 104 additions and 91 deletions
|
|
@ -42,32 +42,7 @@ main {
|
||||||
align-content: center;
|
align-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bar-afond {
|
.bar {
|
||||||
background: black;
|
|
||||||
width: 10px;
|
|
||||||
height: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bar-creatif {
|
|
||||||
background: red;
|
|
||||||
width: 10px;
|
|
||||||
height: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bar-frigo {
|
|
||||||
background: gray;
|
|
||||||
width: 10px;
|
|
||||||
height: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bar-croisiere {
|
|
||||||
background: green;
|
|
||||||
width: 10px;
|
|
||||||
height: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bar-en-charge {
|
|
||||||
background: orange;
|
|
||||||
width: 10px;
|
width: 10px;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
}
|
}
|
||||||
|
|
@ -86,31 +61,6 @@ main {
|
||||||
height: 15px;
|
height: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.creatif {
|
|
||||||
background-color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unknown {
|
|
||||||
border: 2px double grey;
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.en-charge {
|
|
||||||
background-color: orange;
|
|
||||||
}
|
|
||||||
|
|
||||||
.frigo-vide {
|
|
||||||
background-color: grey;
|
|
||||||
}
|
|
||||||
|
|
||||||
.croisiere {
|
|
||||||
background-color: green;
|
|
||||||
}
|
|
||||||
|
|
||||||
.afond {
|
|
||||||
background-color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info {
|
.info {
|
||||||
margin: 30px;
|
margin: 30px;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,15 @@
|
||||||
module MoodsHelper
|
module MoodsHelper
|
||||||
def mode_for(mood, user)
|
def mode_for(mood, user)
|
||||||
if user.guess?
|
if user.guess?
|
||||||
mood[:mode] || mood[:guess] || "unknown"
|
mood[:mode] || mood[:guess] || { label: "unknown", color: "white" }
|
||||||
else
|
else
|
||||||
mood[:mode] || "unknown"
|
mood[:mode] || { label: "unknown", color: "white" }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def style_for_mode(mode)
|
||||||
|
style = "background-color: #{mode[:color]};"
|
||||||
|
style += " border: 2px double grey;" if mode[:label] == "unknown"
|
||||||
|
style
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,16 @@ export default class extends Controller {
|
||||||
image.src = event.target.dataset.image;
|
image.src = event.target.dataset.image;
|
||||||
modeDay.textContent = modeDayContent;
|
modeDay.textContent = modeDayContent;
|
||||||
event.target.className = "selected-day " + event.target.dataset.mode;
|
event.target.className = "selected-day " + event.target.dataset.mode;
|
||||||
|
|
||||||
|
if (this.lastTarget) {
|
||||||
|
this.lastTarget.className = "day " + this.lastTarget.dataset.mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lastTarget = event.target;
|
||||||
}
|
}
|
||||||
|
|
||||||
connect() {
|
connect() {
|
||||||
|
this.lastTarget = null;
|
||||||
window.location = "#end";
|
window.location = "#end";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
3
app/models/mode.rb
Normal file
3
app/models/mode.rb
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
class Mode < ApplicationRecord
|
||||||
|
belongs_to :user
|
||||||
|
end
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
class Mood < ApplicationRecord
|
class Mood < ApplicationRecord
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
|
belongs_to :mode
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ class User < ApplicationRecord
|
||||||
has_secure_password
|
has_secure_password
|
||||||
has_many :sessions, dependent: :destroy
|
has_many :sessions, dependent: :destroy
|
||||||
has_many :moods, -> { order "recorded_at" }
|
has_many :moods, -> { order "recorded_at" }
|
||||||
|
has_many :modes
|
||||||
|
|
||||||
normalizes :email_address, with: ->(e) { e.strip.downcase }
|
normalizes :email_address, with: ->(e) { e.strip.downcase }
|
||||||
|
|
||||||
|
|
@ -34,7 +35,7 @@ class User < ApplicationRecord
|
||||||
MoodCalendarService.generate_calendar(moods)
|
MoodCalendarService.generate_calendar(moods)
|
||||||
end
|
end
|
||||||
|
|
||||||
def current_mood
|
def current_mode
|
||||||
self.moods.last&.mode || "croisiere"
|
self.moods.last&.mode || "croisiere"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@
|
||||||
class MoodCalendarService
|
class MoodCalendarService
|
||||||
def self.generate_calendar(moods, start_date: nil, end_date: Date.current)
|
def self.generate_calendar(moods, start_date: nil, end_date: Date.current)
|
||||||
# Convertir la relation ActiveRecord en tableau de hash
|
# Convertir la relation ActiveRecord en tableau de hash
|
||||||
data = moods.order(:recorded_at)
|
data = moods.joins(:mode)
|
||||||
.pluck(:mode, :recorded_at)
|
.order(:recorded_at)
|
||||||
.map { |mode, recorded_at| { mode: mode, recorded_at: recorded_at } }
|
.pluck(:recorded_at, "modes.label", "modes.color")
|
||||||
|
.map { |recorded_at, label, color| { mode: { label: label, color: color }, recorded_at: recorded_at } }
|
||||||
|
|
||||||
if data.empty?
|
if data.empty?
|
||||||
start_date = Date.current
|
start_date = Date.current
|
||||||
|
|
@ -43,28 +43,21 @@ class MoodCalendarService
|
||||||
# Regrouper par mois avec semaines commençant au premier lundi
|
# Regrouper par mois avec semaines commençant au premier lundi
|
||||||
complete_data.group_by { |d| d[:recorded_at].to_date.beginning_of_month }
|
complete_data.group_by { |d| d[:recorded_at].to_date.beginning_of_month }
|
||||||
.map do |month_start, month_data|
|
.map do |month_start, month_data|
|
||||||
# Trouver le premier lundi du mois (à partir du 1er du mois)
|
|
||||||
first_monday = month_start
|
first_monday = month_start
|
||||||
first_monday = first_monday.next_occurring(:monday) unless first_monday.monday?
|
first_monday = first_monday.next_occurring(:monday) unless first_monday.monday?
|
||||||
|
|
||||||
# Trouver le premier lundi du mois SUIVANT
|
|
||||||
next_month_start = month_start.next_month.beginning_of_month
|
next_month_start = month_start.next_month.beginning_of_month
|
||||||
next_first_monday = next_month_start
|
next_first_monday = next_month_start
|
||||||
next_first_monday = next_first_monday.next_occurring(:monday) unless next_first_monday.monday?
|
next_first_monday = next_first_monday.next_occurring(:monday) unless next_first_monday.monday?
|
||||||
|
|
||||||
# Le dernier jour du mois est le dimanche précédant le premier lundi du mois suivant
|
|
||||||
month_end = next_first_monday - 1.day
|
month_end = next_first_monday - 1.day
|
||||||
|
|
||||||
# Créer un hash pour accès rapide aux données de complete_data (qui contient déjà les guess)
|
|
||||||
data_hash = complete_data.index_by { |d| d[:recorded_at].to_date }
|
data_hash = complete_data.index_by { |d| d[:recorded_at].to_date }
|
||||||
|
|
||||||
# Générer tous les jours du premier lundi jusqu'au dimanche avant le prochain lundi
|
|
||||||
all_days = (first_monday..month_end).map do |date|
|
all_days = (first_monday..month_end).map do |date|
|
||||||
# Utiliser directement les données de complete_data qui ont déjà le bon guess
|
|
||||||
data_hash[date] || { mode: nil, recorded_at: date.to_datetime, guess: nil }
|
data_hash[date] || { mode: nil, recorded_at: date.to_datetime, guess: nil }
|
||||||
end
|
end
|
||||||
|
|
||||||
# Grouper par semaines
|
|
||||||
weeks = all_days.group_by { |d| d[:recorded_at].to_date.beginning_of_week(:monday) }
|
weeks = all_days.group_by { |d| d[:recorded_at].to_date.beginning_of_week(:monday) }
|
||||||
.sort_by { |week_start, _| week_start }
|
.sort_by { |week_start, _| week_start }
|
||||||
.map { |_, week_moods| week_moods }
|
.map { |_, week_moods| week_moods }
|
||||||
|
|
@ -75,4 +68,4 @@ class MoodCalendarService
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end#
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="current-day column is-hidden-mobile">
|
<div class="current-day column is-hidden-mobile">
|
||||||
<section class="m-4">
|
<section class="m-4">
|
||||||
<figure class="image has-ratio">
|
<figure class="image has-ratio">
|
||||||
<%= image_tag(@user.current_mood + ".jpg", "data-mood-target": "image") %>
|
<%= image_tag(@user.current_mode.label + ".jpg", "data-mood-target": "image") %>
|
||||||
</figure>
|
</figure>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -12,31 +12,17 @@
|
||||||
<div class="is-flex is-align-items-center mr-4">
|
<div class="is-flex is-align-items-center mr-4">
|
||||||
<div class=""><strong>Légende</strong></div>
|
<div class=""><strong>Légende</strong></div>
|
||||||
</div>
|
</div>
|
||||||
|
<% @user.modes.each do |mode| %>
|
||||||
<div class="is-flex is-align-items-center mr-4">
|
<div class="is-flex is-align-items-center mr-4">
|
||||||
<div class="bar-frigo mr-1"></div>
|
<div class="bar mr-1" style="<%= style_for_mode(mode) %>"></div>
|
||||||
<div class="">Triste</div>
|
<div class=""><%= mode.label %></div>
|
||||||
</div>
|
|
||||||
<div class="is-flex is-align-items-center mr-4">
|
|
||||||
<div class="bar-en-charge mr-1"></div>
|
|
||||||
<div class="">En charge</div>
|
|
||||||
</div>
|
|
||||||
<div class="is-flex is-align-items-center mr-4">
|
|
||||||
<div class="bar-croisiere mr-1"></div>
|
|
||||||
<div class="">Croisiere</div>
|
|
||||||
</div>
|
|
||||||
<div class="is-flex is-align-items-center mr-4">
|
|
||||||
<div class="bar-creatif mr-1"></div>
|
|
||||||
<div>Creatif</div>
|
|
||||||
</div>
|
|
||||||
<div class="is-flex is-align-items-center mr-4">
|
|
||||||
<div class="bar-afond mr-1"></div>
|
|
||||||
<div class="">A fond</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<div class="container mb-4 p-3 has-background-white day-info">
|
<div class="container mb-4 p-3 has-background-white day-info">
|
||||||
<div class="title is-4">
|
<div class="title is-4">
|
||||||
<span class="icon"><i class="fa-regular fa-calendar"></i></span>
|
<span class="icon"><i class="fa-regular fa-calendar"></i></span>
|
||||||
<span data-mood-target="modeDay">Aujourd'hui : <%= @user.current_mood %></span>
|
<span data-mood-target="modeDay">Aujourd'hui : <%= @user.current_mode.label %></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="logs">
|
<div class="logs">
|
||||||
|
|
@ -49,7 +35,7 @@
|
||||||
<div class="is-flex is-flex-direction-column is-flex-wrap-wrap mb-3">
|
<div class="is-flex is-flex-direction-column is-flex-wrap-wrap mb-3">
|
||||||
<% week.each do |mood| %>
|
<% week.each do |mood| %>
|
||||||
<% mode = mode_for(mood, @user) %>
|
<% mode = mode_for(mood, @user) %>
|
||||||
<div data-image="<%= asset_path(mode + ".jpg") %>" data-mode="<%= mode %>" data-day="<%= l mood[:recorded_at].to_date %>" data-action="click->mood#updateDayInfo" title="<%= l(mood[:recorded_at].to_date) %> : <%= mode %>" class="day <%= mode %>"></div>
|
<div data-image="<%= asset_path(mode[:label] + ".jpg") %>" data-mode="<%= mode[:label] %>" data-day="<%= l mood[:recorded_at].to_date %>" data-action="click->mood#updateDayInfo" title="<%= l(mood[:recorded_at].to_date) %> : <%= mode[:label] %>" class="day" style="<%= style_for_mode(mode) %>"></div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
||||||
11
db/migrate/20260314144625_create_modes.rb
Normal file
11
db/migrate/20260314144625_create_modes.rb
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
class CreateModes < ActiveRecord::Migration[8.0]
|
||||||
|
def change
|
||||||
|
create_table :modes do |t|
|
||||||
|
t.string :label
|
||||||
|
t.string :color
|
||||||
|
t.references :user, null: false, foreign_key: true
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
class ReplaceMoodModeStringWithModeReference < ActiveRecord::Migration[8.0]
|
||||||
|
def up
|
||||||
|
# 1. Ajouter la colonne de référence
|
||||||
|
add_reference :moods, :mode, foreign_key: true
|
||||||
|
|
||||||
|
# 2. Pour chaque mood, trouver ou créer le Mode correspondant
|
||||||
|
Mood.find_each do |mood|
|
||||||
|
next if mood.mode.blank?
|
||||||
|
|
||||||
|
mode_record = Mode.find_or_create_by!(label: mood.mode, user_id: mood.user_id) do |m|
|
||||||
|
m.color = "#000000" # couleur par défaut
|
||||||
|
end
|
||||||
|
|
||||||
|
mood.update_column(:mode_id, mode_record.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
# 3. Supprimer l'ancienne colonne string
|
||||||
|
remove_column :moods, :mode, :string
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
add_column :moods, :mode, :string
|
||||||
|
|
||||||
|
Mood.find_each do |mood|
|
||||||
|
mood.update_column(:mode, mood.mode&.label)
|
||||||
|
end
|
||||||
|
|
||||||
|
remove_reference :moods, :mode, foreign_key: true
|
||||||
|
end
|
||||||
|
end
|
||||||
16
db/schema.rb
generated
16
db/schema.rb
generated
|
|
@ -10,13 +10,23 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[8.0].define(version: 2026_02_26_101258) do
|
ActiveRecord::Schema[8.0].define(version: 2026_03_14_150724) do
|
||||||
|
create_table "modes", force: :cascade do |t|
|
||||||
|
t.string "label"
|
||||||
|
t.string "color"
|
||||||
|
t.integer "user_id", null: false
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.index ["user_id"], name: "index_modes_on_user_id"
|
||||||
|
end
|
||||||
|
|
||||||
create_table "moods", force: :cascade do |t|
|
create_table "moods", force: :cascade do |t|
|
||||||
t.string "mode"
|
|
||||||
t.datetime "recorded_at"
|
t.datetime "recorded_at"
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.integer "user_id"
|
t.integer "user_id"
|
||||||
|
t.integer "mode_id"
|
||||||
|
t.index ["mode_id"], name: "index_moods_on_mode_id"
|
||||||
t.index ["user_id"], name: "index_moods_on_user_id"
|
t.index ["user_id"], name: "index_moods_on_user_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -52,6 +62,8 @@ ActiveRecord::Schema[8.0].define(version: 2026_02_26_101258) do
|
||||||
t.index ["email_address"], name: "index_users_on_email_address", unique: true
|
t.index ["email_address"], name: "index_users_on_email_address", unique: true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
add_foreign_key "modes", "users"
|
||||||
|
add_foreign_key "moods", "modes"
|
||||||
add_foreign_key "moods", "users"
|
add_foreign_key "moods", "users"
|
||||||
add_foreign_key "rfid_tags", "users"
|
add_foreign_key "rfid_tags", "users"
|
||||||
add_foreign_key "sessions", "users"
|
add_foreign_key "sessions", "users"
|
||||||
|
|
|
||||||
8
spec/factories/modes.rb
Normal file
8
spec/factories/modes.rb
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
FactoryBot.define do
|
||||||
|
factory :mode do
|
||||||
|
label { "MyString" }
|
||||||
|
slug { "MyString" }
|
||||||
|
color { "MyString" }
|
||||||
|
user { nil }
|
||||||
|
end
|
||||||
|
end
|
||||||
5
spec/models/mode_spec.rb
Normal file
5
spec/models/mode_spec.rb
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe Mode, type: :model do
|
||||||
|
pending "add some examples to (or delete) #{__FILE__}"
|
||||||
|
end
|
||||||
Loading…
Add table
Reference in a new issue