12 Added notes and colours to customers
This commit is contained in:
@@ -27,4 +27,126 @@
|
|||||||
|
|
||||||
.calendar-time-slot {
|
.calendar-time-slot {
|
||||||
min-height: 50px; /* Adjust as needed */
|
min-height: 50px; /* Adjust as needed */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ToastUI Calendar Event Styling */
|
||||||
|
.toastui-calendar-events {
|
||||||
|
margin-right: 8px;
|
||||||
|
text-wrap: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toastui-calendar-event-time {
|
||||||
|
position: relative;
|
||||||
|
overflow: visible !important;
|
||||||
|
min-height: 24px !important;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toastui-calendar-event-time:hover {
|
||||||
|
transform: scale(1.02);
|
||||||
|
z-index: 1000 !important;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
|
border-radius: 4px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toastui-calendar-event-time-content {
|
||||||
|
height: 100% !important;
|
||||||
|
overflow: visible !important;
|
||||||
|
padding: 2px 4px !important;
|
||||||
|
text-wrap: auto;
|
||||||
|
word-wrap: break-word;
|
||||||
|
line-height: 1.1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toastui-calendar-template-time {
|
||||||
|
font-size: 10px !important;
|
||||||
|
line-height: 1.1 !important;
|
||||||
|
text-wrap: auto;
|
||||||
|
word-wrap: break-word;
|
||||||
|
white-space: normal !important;
|
||||||
|
overflow: visible !important;
|
||||||
|
display: block !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toastui-calendar-template-time strong {
|
||||||
|
font-size: 10px !important;
|
||||||
|
font-weight: 600;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toastui-calendar-template-time span {
|
||||||
|
font-size: 9px !important;
|
||||||
|
line-height: 1.0 !important;
|
||||||
|
text-wrap: auto;
|
||||||
|
word-wrap: break-word;
|
||||||
|
white-space: normal !important;
|
||||||
|
display: block !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hover tooltip effect */
|
||||||
|
.toastui-calendar-event-time:hover::after {
|
||||||
|
content: "Click to edit reservation";
|
||||||
|
position: absolute;
|
||||||
|
bottom: 100%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
background-color: rgba(0, 0, 0, 0.9);
|
||||||
|
color: white;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 11px;
|
||||||
|
white-space: nowrap;
|
||||||
|
z-index: 2000;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0;
|
||||||
|
animation: tooltipFadeIn 0.3s ease forwards;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.toastui-calendar-event-time:hover::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: calc(100% - 6px);
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
border: 6px solid transparent;
|
||||||
|
border-top-color: rgba(0, 0, 0, 0.9);
|
||||||
|
z-index: 2000;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0;
|
||||||
|
animation: tooltipFadeIn 0.3s ease forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes tooltipFadeIn {
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Improve visibility for small events */
|
||||||
|
.toastui-calendar-event-time[style*="height: calc(1%"] .toastui-calendar-template-time strong,
|
||||||
|
.toastui-calendar-event-time[style*="height: calc(2%"] .toastui-calendar-template-time strong {
|
||||||
|
display: none; /* Hide time for very small events */
|
||||||
|
}
|
||||||
|
|
||||||
|
.toastui-calendar-event-time[style*="height: calc(1%"] .toastui-calendar-template-time span,
|
||||||
|
.toastui-calendar-event-time[style*="height: calc(2%"] .toastui-calendar-template-time span {
|
||||||
|
font-size: 8px !important;
|
||||||
|
line-height: 1.0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure minimum visibility */
|
||||||
|
.toastui-calendar-event-time {
|
||||||
|
min-width: 60px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Better text contrast */
|
||||||
|
.toastui-calendar-event-time[style*="background-color: rgb(66, 109, 215)"] {
|
||||||
|
color: white !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toastui-calendar-event-time[style*="background-color: rgb(66, 109, 215)"] .toastui-calendar-template-time {
|
||||||
|
color: white !important;
|
||||||
|
}
|
||||||
|
|||||||
@@ -64,10 +64,15 @@ class CustomersController < ApplicationController
|
|||||||
).limit(10)
|
).limit(10)
|
||||||
|
|
||||||
render json: @customers.map { |c|
|
render json: @customers.map { |c|
|
||||||
|
label = "#{c.full_name} (#{c.original_phone})"
|
||||||
|
label += " - #{c.notes}" if c.notes.present?
|
||||||
{
|
{
|
||||||
id: "#{c.first_name}_#{c.surname}_#{c.original_phone}",
|
id: "#{c.first_name}_#{c.surname}_#{c.original_phone}",
|
||||||
label: "#{c.full_name} (#{c.original_phone})",
|
label: label,
|
||||||
birthyear: c.birthyear
|
birthyear: c.birthyear,
|
||||||
|
color: c.color || 'green',
|
||||||
|
color_hex: c.color_hex,
|
||||||
|
notes: c.notes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
@@ -86,6 +91,6 @@ class CustomersController < ApplicationController
|
|||||||
|
|
||||||
# Only allow a list of trusted parameters through.
|
# Only allow a list of trusted parameters through.
|
||||||
def customer_params
|
def customer_params
|
||||||
params.require(:customer).permit(:first_name, :surname, :phone, :notes, :email, :birthyear)
|
params.require(:customer).permit(:first_name, :surname, :phone, :notes, :email, :birthyear, :color)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -41,7 +41,10 @@ class ReservationsController < ApplicationController
|
|||||||
# POST /reservations or /reservations.json
|
# POST /reservations or /reservations.json
|
||||||
def create
|
def create
|
||||||
@reservation = @company.reservations.new(
|
@reservation = @company.reservations.new(
|
||||||
reservation_params.except(:customer_id, :customer_birth_year)
|
reservation_params.except(
|
||||||
|
:customer_id, :customer_first_name, :customer_surname,
|
||||||
|
:customer_original_phone, :customer_birth_year, :customer_composite_key
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Find or create customer based on submitted attributes
|
# Find or create customer based on submitted attributes
|
||||||
@@ -68,7 +71,7 @@ class ReservationsController < ApplicationController
|
|||||||
customer_attrs = build_customer_attributes # Use existing helper
|
customer_attrs = build_customer_attributes # Use existing helper
|
||||||
reservation_attrs = reservation_params.except(
|
reservation_attrs = reservation_params.except(
|
||||||
:customer_id, :customer_first_name, :customer_surname,
|
:customer_id, :customer_first_name, :customer_surname,
|
||||||
:customer_original_phone, :customer_birth_year
|
:customer_original_phone, :customer_birth_year, :customer_composite_key
|
||||||
)
|
)
|
||||||
|
|
||||||
# Find the customer identified by the submitted name/phone
|
# Find the customer identified by the submitted name/phone
|
||||||
@@ -144,6 +147,7 @@ class ReservationsController < ApplicationController
|
|||||||
:customer_surname,
|
:customer_surname,
|
||||||
:customer_original_phone,
|
:customer_original_phone,
|
||||||
:customer_birth_year,
|
:customer_birth_year,
|
||||||
|
:customer_composite_key,
|
||||||
:customer_id # Allow this if select still sends it sometimes
|
:customer_id # Allow this if select still sends it sometimes
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -66,7 +66,8 @@ export default class extends Controller {
|
|||||||
return '<div class="no-results">No customers found. Fill in the details below.</div>';
|
return '<div class="no-results">No customers found. Fill in the details below.</div>';
|
||||||
},
|
},
|
||||||
option: function(item) {
|
option: function(item) {
|
||||||
return `<div>${item.label}</div>`;
|
const colorStyle = item.color_hex ? `background-color: ${item.color_hex}20; border-left: 4px solid ${item.color_hex};` : '';
|
||||||
|
return `<div style="${colorStyle} padding: 8px;">${item.label}</div>`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -98,6 +99,9 @@ export default class extends Controller {
|
|||||||
if (initialValue) {
|
if (initialValue) {
|
||||||
this.newCustomerFieldsTarget.classList.add('hidden');
|
this.newCustomerFieldsTarget.classList.add('hidden');
|
||||||
this.customerSelected(initialValue);
|
this.customerSelected(initialValue);
|
||||||
|
} else {
|
||||||
|
// Show new customer fields if no existing customer
|
||||||
|
this.showNewCustomerFields();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,4 +152,4 @@ export default class extends Controller {
|
|||||||
this.selectInstance.destroy();
|
this.selectInstance.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,8 @@ export default class extends Controller {
|
|||||||
return ''; // Empty location as requested
|
return ''; // Empty location as requested
|
||||||
},
|
},
|
||||||
popupDetailAttendees(eventObj) {
|
popupDetailAttendees(eventObj) {
|
||||||
return eventObj.attendees[0]; // Show team name
|
const teamName = eventObj.attendees[0]; // Show team name
|
||||||
|
return teamName;
|
||||||
},
|
},
|
||||||
popupDetailState(eventObj) {
|
popupDetailState(eventObj) {
|
||||||
return '';
|
return '';
|
||||||
@@ -148,11 +149,13 @@ export default class extends Controller {
|
|||||||
const startTime = new Date(reservation.start_time);
|
const startTime = new Date(reservation.start_time);
|
||||||
const endTime = new Date(reservation.end_time);
|
const endTime = new Date(reservation.end_time);
|
||||||
|
|
||||||
// Create the event
|
// Create the event with customer name only
|
||||||
|
const customerName = reservation.customer ? `${reservation.customer.first_name} ${reservation.customer.surname}` : '';
|
||||||
|
|
||||||
const event = {
|
const event = {
|
||||||
id: `reservation-${reservation.id}`,
|
id: `reservation-${reservation.id}`,
|
||||||
calendarId: calendarId,
|
calendarId: calendarId,
|
||||||
title: reservation.customer ? `${reservation.customer.first_name} ${reservation.customer.surname}` : '',
|
title: customerName,
|
||||||
start: startTime,
|
start: startTime,
|
||||||
end: endTime,
|
end: endTime,
|
||||||
category: 'time',
|
category: 'time',
|
||||||
@@ -276,4 +279,4 @@ export default class extends Controller {
|
|||||||
// Update calendar display
|
// Update calendar display
|
||||||
window.calendar.render();
|
window.calendar.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ class Customer < ApplicationRecord
|
|||||||
# Use Rails 7.1's native composite primary key
|
# Use Rails 7.1's native composite primary key
|
||||||
self.primary_key = %i[first_name surname original_phone]
|
self.primary_key = %i[first_name surname original_phone]
|
||||||
|
|
||||||
|
attribute :color, :string, default: 'green'
|
||||||
|
|
||||||
belongs_to :company
|
belongs_to :company
|
||||||
|
|
||||||
validates :first_name, presence: true
|
validates :first_name, presence: true
|
||||||
@@ -21,20 +23,65 @@ class Customer < ApplicationRecord
|
|||||||
less_than_or_equal_to: -> { Time.current.year }
|
less_than_or_equal_to: -> { Time.current.year }
|
||||||
}, allow_nil: true
|
}, allow_nil: true
|
||||||
|
|
||||||
|
validates :color, inclusion: { in: %w[green yellow red] }, allow_nil: true
|
||||||
|
|
||||||
before_validation :set_original_phone, on: :create
|
before_validation :set_original_phone, on: :create
|
||||||
|
before_validation :set_default_color, on: :create
|
||||||
|
|
||||||
def full_name
|
def full_name
|
||||||
[first_name, surname].compact_blank.join(' ')
|
[first_name, surname].compact_blank.join(' ')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def green?
|
||||||
|
color == 'green'
|
||||||
|
end
|
||||||
|
|
||||||
|
def yellow?
|
||||||
|
color == 'yellow'
|
||||||
|
end
|
||||||
|
|
||||||
|
def red?
|
||||||
|
color == 'red'
|
||||||
|
end
|
||||||
|
|
||||||
# Add method for URL generation
|
# Add method for URL generation
|
||||||
def to_param
|
def to_param
|
||||||
[first_name, surname, original_phone].join('_')
|
[first_name, surname, original_phone].join('_')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def color_hex
|
||||||
|
case color || 'green'
|
||||||
|
when 'green'
|
||||||
|
'#22c55e'
|
||||||
|
when 'yellow'
|
||||||
|
'#eab308'
|
||||||
|
when 'red'
|
||||||
|
'#ef4444'
|
||||||
|
else
|
||||||
|
'#22c55e'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def color_emoji
|
||||||
|
case color || 'green'
|
||||||
|
when 'green'
|
||||||
|
'🟩'
|
||||||
|
when 'yellow'
|
||||||
|
'🟨'
|
||||||
|
when 'red'
|
||||||
|
'🟥'
|
||||||
|
else
|
||||||
|
'🟩'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_original_phone
|
def set_original_phone
|
||||||
self.original_phone = phone if original_phone.blank?
|
self.original_phone = phone if original_phone.blank?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_default_color
|
||||||
|
self.color = 'green' if color.blank?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
class ReservationSerializer < ActiveModel::Serializer
|
class ReservationSerializer < ActiveModel::Serializer
|
||||||
attributes :id, :start_time, :end_time
|
attributes :id, :start_time, :end_time, :customer_color_emoji
|
||||||
|
|
||||||
belongs_to :customer
|
belongs_to :customer
|
||||||
belongs_to :team, serializer: TeamSerializer
|
belongs_to :team, serializer: TeamSerializer
|
||||||
end
|
|
||||||
|
def customer_color_emoji
|
||||||
|
object.customer&.color_emoji || ''
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
@@ -19,6 +19,14 @@
|
|||||||
<%= customer.notes %>
|
<%= customer.notes %>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p class="my-5">
|
||||||
|
<strong class="block font-medium mb-1">Color:</strong>
|
||||||
|
<span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium"
|
||||||
|
style="background-color: <%= customer.color_hex %>20; color: <%= customer.color_hex %>; border: 1px solid <%= customer.color_hex %>;">
|
||||||
|
<%= customer.color_emoji %> <%= (customer.color || 'green').humanize %>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
<p class="my-5">
|
<p class="my-5">
|
||||||
<strong class="block font-medium mb-1">Email:</strong>
|
<strong class="block font-medium mb-1">Email:</strong>
|
||||||
<%= customer.email %>
|
<%= customer.email %>
|
||||||
|
|||||||
@@ -31,6 +31,18 @@
|
|||||||
<%= form.text_area :notes, rows: 4, class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full" %>
|
<%= form.text_area :notes, rows: 4, class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full" %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="my-5">
|
||||||
|
<%= form.label :color %>
|
||||||
|
<%= form.select :color,
|
||||||
|
options_for_select([
|
||||||
|
['Green', 'green'],
|
||||||
|
['Yellow', 'yellow'],
|
||||||
|
['Red', 'red']
|
||||||
|
], customer.color),
|
||||||
|
{ prompt: 'Select color' },
|
||||||
|
{ class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full" } %>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="my-5">
|
<div class="my-5">
|
||||||
<%= form.label :email %>
|
<%= form.label :email %>
|
||||||
<%= form.text_field :email, class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full" %>
|
<%= form.text_field :email, class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full" %>
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
<link rel="stylesheet" href="https://rsms.me/inter/inter.css">
|
<link rel="stylesheet" href="https://rsms.me/inter/inter.css">
|
||||||
<%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %>
|
<%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %>
|
||||||
|
|
||||||
|
|
||||||
<%= javascript_importmap_tags %>
|
<%= javascript_importmap_tags %>
|
||||||
<style>
|
<style>
|
||||||
html, body {
|
html, body {
|
||||||
@@ -51,6 +50,114 @@
|
|||||||
padding: 5px;
|
padding: 5px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ToastUI Calendar Event Styling */
|
||||||
|
.toastui-calendar-events {
|
||||||
|
margin-right: 8px;
|
||||||
|
text-wrap: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toastui-calendar-event-time {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
min-width: 50px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toastui-calendar-event-time:hover {
|
||||||
|
z-index: 1000 !important;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
||||||
|
border-radius: 3px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toastui-calendar-event-time-content {
|
||||||
|
padding: 2px 4px !important;
|
||||||
|
text-wrap: auto;
|
||||||
|
word-wrap: break-word;
|
||||||
|
line-height: 1.1 !important;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toastui-calendar-template-time {
|
||||||
|
font-size: 10px !important;
|
||||||
|
line-height: 1.1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toastui-calendar-template-time strong {
|
||||||
|
font-size: 10px !important;
|
||||||
|
font-weight: 600;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toastui-calendar-template-time span {
|
||||||
|
font-size: 9px !important;
|
||||||
|
line-height: 1.0 !important;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hover tooltip effect */
|
||||||
|
.toastui-calendar-event-time:hover::after {
|
||||||
|
content: "Click to edit reservation";
|
||||||
|
position: absolute;
|
||||||
|
bottom: 100%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
background-color: rgba(0, 0, 0, 0.9);
|
||||||
|
color: white;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 11px;
|
||||||
|
white-space: nowrap;
|
||||||
|
z-index: 2000;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0;
|
||||||
|
animation: tooltipFadeIn 0.3s ease forwards;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.toastui-calendar-event-time:hover::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: calc(100% - 6px);
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
border: 6px solid transparent;
|
||||||
|
border-top-color: rgba(0, 0, 0, 0.9);
|
||||||
|
z-index: 2000;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0;
|
||||||
|
animation: tooltipFadeIn 0.3s ease forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes tooltipFadeIn {
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Improve visibility for small events */
|
||||||
|
.toastui-calendar-event-time[style*="height: calc(1%"] .toastui-calendar-template-time strong,
|
||||||
|
.toastui-calendar-event-time[style*="height: calc(2%"] .toastui-calendar-template-time strong {
|
||||||
|
display: none; /* Hide time for very small events */
|
||||||
|
}
|
||||||
|
|
||||||
|
.toastui-calendar-event-time[style*="height: calc(1%"] .toastui-calendar-template-time span,
|
||||||
|
.toastui-calendar-event-time[style*="height: calc(2%"] .toastui-calendar-template-time span {
|
||||||
|
font-size: 8px !important;
|
||||||
|
line-height: 1.0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Better text contrast */
|
||||||
|
.toastui-calendar-event-time[style*="background-color: rgb(66, 109, 215)"] {
|
||||||
|
color: white !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toastui-calendar-event-time[style*="background-color: rgb(66, 109, 215)"] .toastui-calendar-template-time {
|
||||||
|
color: white !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@@ -60,4 +167,4 @@
|
|||||||
</main>
|
</main>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
want
|
want
|
||||||
|
|||||||
@@ -28,14 +28,13 @@
|
|||||||
} %>
|
} %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div data-customer-search-target="newCustomerFields" class="">
|
||||||
<div class="my-5">
|
<div class="my-5">
|
||||||
<%= form.label :phone_number, t('reservations.form.phone_number') %>
|
<%= form.label :phone_number, t('reservations.form.phone_number') %>
|
||||||
<%= form.telephone_field :customer_original_phone,
|
<%= form.telephone_field :customer_original_phone,
|
||||||
class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full",
|
class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full",
|
||||||
data: { customer_search_target: "phoneField" } %>
|
data: { customer_search_target: "phoneField" } %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div data-customer-search-target="newCustomerFields" class="hidden">
|
|
||||||
<div class="my-5">
|
<div class="my-5">
|
||||||
<%= form.label :first_name, t('reservations.form.first_name') %>
|
<%= form.label :first_name, t('reservations.form.first_name') %>
|
||||||
<%= form.text_field :customer_first_name,
|
<%= form.text_field :customer_first_name,
|
||||||
@@ -56,6 +55,8 @@
|
|||||||
class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full",
|
class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full",
|
||||||
data: { customer_search_target: "birthYearField" } %>
|
data: { customer_search_target: "birthYearField" } %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="my-5">
|
<div class="my-5">
|
||||||
|
|||||||
@@ -65,4 +65,4 @@
|
|||||||
%>
|
%>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -33,6 +33,11 @@ bs:
|
|||||||
first_name: "Ime"
|
first_name: "Ime"
|
||||||
surname: "Prezime"
|
surname: "Prezime"
|
||||||
birth_year: "Godina rođenja"
|
birth_year: "Godina rođenja"
|
||||||
|
customer_color: "Boja klijenta"
|
||||||
|
select_color: "Odaberite boju klijenta"
|
||||||
|
green: "Zelena"
|
||||||
|
yellow: "Žuta"
|
||||||
|
red: "Crvena"
|
||||||
team: "Tim"
|
team: "Tim"
|
||||||
select_team: "Odaberite tim"
|
select_team: "Odaberite tim"
|
||||||
start_time: "Vrijeme početka"
|
start_time: "Vrijeme početka"
|
||||||
|
|||||||
@@ -77,6 +77,11 @@ en:
|
|||||||
first_name: "First name"
|
first_name: "First name"
|
||||||
surname: "Surname"
|
surname: "Surname"
|
||||||
birth_year: "Birth year"
|
birth_year: "Birth year"
|
||||||
|
customer_color: "Customer color"
|
||||||
|
select_color: "Select customer color"
|
||||||
|
green: "Green"
|
||||||
|
yellow: "Yellow"
|
||||||
|
red: "Red"
|
||||||
team: "Team"
|
team: "Team"
|
||||||
select_team: "Select a team"
|
select_team: "Select a team"
|
||||||
start_time: "Start time"
|
start_time: "Start time"
|
||||||
|
|||||||
5
db/migrate/20250704091649_add_color_to_customers.rb
Normal file
5
db/migrate/20250704091649_add_color_to_customers.rb
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
class AddColorToCustomers < ActiveRecord::Migration[7.1]
|
||||||
|
def change
|
||||||
|
add_column :customers, :color, :string
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
class UpdateExistingCustomersColor < ActiveRecord::Migration[7.1]
|
||||||
|
def up
|
||||||
|
Customer.where(color: nil).update_all(color: 'green')
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
# No rollback needed - we don't want to set colors back to nil
|
||||||
|
end
|
||||||
|
end
|
||||||
3
db/schema.rb
generated
3
db/schema.rb
generated
@@ -10,7 +10,7 @@
|
|||||||
#
|
#
|
||||||
# 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[7.1].define(version: 2025_02_18_071800) do
|
ActiveRecord::Schema[7.1].define(version: 2025_07_04_092438) do
|
||||||
create_table "companies", force: :cascade do |t|
|
create_table "companies", force: :cascade do |t|
|
||||||
t.string "name"
|
t.string "name"
|
||||||
t.string "id_number"
|
t.string "id_number"
|
||||||
@@ -36,6 +36,7 @@ ActiveRecord::Schema[7.1].define(version: 2025_02_18_071800) do
|
|||||||
t.string "first_name"
|
t.string "first_name"
|
||||||
t.string "surname", null: false
|
t.string "surname", null: false
|
||||||
t.string "original_phone", null: false
|
t.string "original_phone", null: false
|
||||||
|
t.string "color"
|
||||||
t.index ["company_id"], name: "index_customers_on_company_id"
|
t.index ["company_id"], name: "index_customers_on_company_id"
|
||||||
t.index ["first_name", "surname", "original_phone", "company_id"], name: "index_customers_on_composite_key_and_company", unique: true
|
t.index ["first_name", "surname", "original_phone", "company_id"], name: "index_customers_on_composite_key_and_company", unique: true
|
||||||
t.index ["first_name", "surname", "original_phone"], name: "index_customers_on_composite_key", unique: true
|
t.index ["first_name", "surname", "original_phone"], name: "index_customers_on_composite_key", unique: true
|
||||||
|
|||||||
Reference in New Issue
Block a user