754 lines
25 KiB
TypeScript
754 lines
25 KiB
TypeScript
/**
|
||
* Диалог создания занятия в Material Design 3
|
||
*/
|
||
|
||
'use client';
|
||
|
||
import React, { useState, useEffect } from 'react';
|
||
import { loadComponent } from '@/lib/material-components';
|
||
import { createLesson } from '@/api/schedule';
|
||
import { getStudents, Student } from '@/api/students';
|
||
import { getSubjects, getMentorSubjects, createMentorSubject, Subject, MentorSubject } from '@/api/subjects';
|
||
import { getCurrentUser, User } from '@/api/auth';
|
||
import { format } from 'date-fns';
|
||
|
||
interface CreateLessonDialogProps {
|
||
open: boolean;
|
||
onClose: () => void;
|
||
onSuccess: () => void;
|
||
defaultDate?: Date;
|
||
}
|
||
|
||
interface LessonFormData {
|
||
client: string;
|
||
title: string;
|
||
subject_id?: number;
|
||
mentor_subject_id?: number;
|
||
subject_name?: string;
|
||
description: string;
|
||
start_date: string; // YYYY-MM-DD
|
||
start_time: string; // HH:mm
|
||
duration: number;
|
||
price?: number;
|
||
is_recurring: boolean;
|
||
}
|
||
|
||
export const CreateLessonDialog: React.FC<CreateLessonDialogProps> = ({
|
||
open,
|
||
onClose,
|
||
onSuccess,
|
||
defaultDate,
|
||
}) => {
|
||
const [componentsLoaded, setComponentsLoaded] = useState(false);
|
||
const [loading, setLoading] = useState(false);
|
||
const [error, setError] = useState<string | null>(null);
|
||
|
||
const [students, setStudents] = useState<Student[]>([]);
|
||
const [subjects, setSubjects] = useState<Subject[]>([]);
|
||
const [mentorSubjects, setMentorSubjects] = useState<MentorSubject[]>([]);
|
||
const [currentUser, setCurrentUser] = useState<User | null>(null);
|
||
|
||
const [selectedSubjectId, setSelectedSubjectId] = useState<number | null>(null);
|
||
const [selectedMentorSubjectId, setSelectedMentorSubjectId] = useState<number | null>(null);
|
||
const [customSubjectName, setCustomSubjectName] = useState<string>('');
|
||
|
||
const [formData, setFormData] = useState<LessonFormData>({
|
||
client: '',
|
||
title: '',
|
||
description: '',
|
||
start_date: '',
|
||
start_time: '',
|
||
duration: 60,
|
||
price: undefined,
|
||
is_recurring: false,
|
||
});
|
||
|
||
useEffect(() => {
|
||
if (open) {
|
||
loadComponents();
|
||
loadData();
|
||
}
|
||
}, [open]);
|
||
|
||
useEffect(() => {
|
||
if (open && defaultDate) {
|
||
const start = new Date(defaultDate);
|
||
|
||
const formatDate = (date: Date) => {
|
||
const year = date.getFullYear();
|
||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||
const day = String(date.getDate()).padStart(2, '0');
|
||
return `${year}-${month}-${day}`;
|
||
};
|
||
|
||
const formatTime = (date: Date) => {
|
||
const hours = String(date.getHours()).padStart(2, '0');
|
||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||
return `${hours}:${minutes}`;
|
||
};
|
||
|
||
setFormData(prev => ({
|
||
...prev,
|
||
start_date: formatDate(start),
|
||
start_time: formatTime(start),
|
||
}));
|
||
}
|
||
}, [open, defaultDate]);
|
||
|
||
const loadComponents = async () => {
|
||
try {
|
||
await Promise.all([
|
||
loadComponent('dialog'),
|
||
loadComponent('filled-button'),
|
||
loadComponent('text-button'),
|
||
loadComponent('outlined-field'),
|
||
loadComponent('select'),
|
||
loadComponent('switch'),
|
||
loadComponent('icon'),
|
||
]);
|
||
setComponentsLoaded(true);
|
||
} catch (error) {
|
||
console.error('[CreateLessonDialog] Ошибка загрузки компонентов:', error);
|
||
}
|
||
};
|
||
|
||
const loadData = async () => {
|
||
try {
|
||
const [studentsData, subjectsData, mentorSubjectsData, userData] = await Promise.all([
|
||
getStudents({ page_size: 100 }),
|
||
getSubjects(),
|
||
getMentorSubjects(),
|
||
getCurrentUser(),
|
||
]);
|
||
|
||
const studentsList = Array.isArray(studentsData) ? studentsData : (studentsData.results || []);
|
||
setStudents(studentsList);
|
||
setSubjects(Array.isArray(subjectsData) ? subjectsData : []);
|
||
setMentorSubjects(Array.isArray(mentorSubjectsData) ? mentorSubjectsData : []);
|
||
setCurrentUser(userData);
|
||
} catch (error) {
|
||
console.error('[CreateLessonDialog] Ошибка загрузки данных:', error);
|
||
setError('Ошибка загрузки данных');
|
||
}
|
||
};
|
||
|
||
const generateTitle = (student: Student | null, subjectName: string): string => {
|
||
if (!student || !subjectName || !currentUser) return '';
|
||
|
||
const mentorName = `${currentUser.last_name} ${currentUser.first_name?.charAt(0) || ''}.`.trim();
|
||
const studentName = `${student.user?.last_name || ''} ${student.user?.first_name?.charAt(0) || ''}.`.trim();
|
||
|
||
return `${mentorName} ${studentName} ${subjectName}`.trim();
|
||
};
|
||
|
||
const getSubjectName = (): string => {
|
||
if (selectedSubjectId) {
|
||
const subject = subjects.find(s => s.id === selectedSubjectId);
|
||
return subject?.name || '';
|
||
}
|
||
if (selectedMentorSubjectId) {
|
||
const subject = mentorSubjects.find(s => s.id === selectedMentorSubjectId);
|
||
return subject?.name || '';
|
||
}
|
||
return customSubjectName || '';
|
||
};
|
||
|
||
// Автогенерация названия
|
||
useEffect(() => {
|
||
if (formData.client && getSubjectName() && currentUser) {
|
||
const selectedStudent = students.find(s => String(s.id) === formData.client);
|
||
if (selectedStudent) {
|
||
const subjectName = getSubjectName();
|
||
const generatedTitle = generateTitle(selectedStudent, subjectName);
|
||
setFormData(prev => ({ ...prev, title: generatedTitle }));
|
||
}
|
||
}
|
||
}, [formData.client, selectedSubjectId, selectedMentorSubjectId, customSubjectName, students, currentUser, subjects, mentorSubjects]);
|
||
|
||
const handleSubjectChange = async (value: string | number | null, isCustom: boolean, customName?: string) => {
|
||
if (isCustom && customName) {
|
||
setSelectedSubjectId(null);
|
||
setSelectedMentorSubjectId(null);
|
||
setCustomSubjectName(customName);
|
||
} else if (value) {
|
||
const subject = subjects.find(s => s.id === value);
|
||
const mentorSubject = mentorSubjects.find(s => s.id === value);
|
||
|
||
if (subject) {
|
||
setSelectedSubjectId(subject.id);
|
||
setSelectedMentorSubjectId(null);
|
||
setCustomSubjectName('');
|
||
} else if (mentorSubject) {
|
||
setSelectedSubjectId(null);
|
||
setSelectedMentorSubjectId(mentorSubject.id);
|
||
setCustomSubjectName('');
|
||
}
|
||
} else {
|
||
setSelectedSubjectId(null);
|
||
setSelectedMentorSubjectId(null);
|
||
setCustomSubjectName('');
|
||
}
|
||
};
|
||
|
||
const handleCustomSubjectCreate = async (name: string): Promise<void> => {
|
||
const newSubject = await createMentorSubject(name);
|
||
setMentorSubjects(prev => [...prev, newSubject]);
|
||
setSelectedMentorSubjectId(newSubject.id);
|
||
setCustomSubjectName('');
|
||
};
|
||
|
||
const handleDateChange = (value: string) => {
|
||
setFormData(prev => ({
|
||
...prev,
|
||
start_date: value,
|
||
}));
|
||
};
|
||
|
||
const handleTimeChange = (value: string) => {
|
||
setFormData(prev => ({
|
||
...prev,
|
||
start_time: value,
|
||
}));
|
||
};
|
||
|
||
const handleDurationChange = (value: number) => {
|
||
setFormData(prev => ({
|
||
...prev,
|
||
duration: value,
|
||
}));
|
||
};
|
||
|
||
const handleSubmit = async (e: React.FormEvent) => {
|
||
e.preventDefault();
|
||
setLoading(true);
|
||
setError(null);
|
||
|
||
try {
|
||
if (!formData.client) {
|
||
setError('Выберите ученика');
|
||
setLoading(false);
|
||
return;
|
||
}
|
||
|
||
if (!selectedSubjectId && !selectedMentorSubjectId && !customSubjectName) {
|
||
setError('Выберите или введите предмет');
|
||
setLoading(false);
|
||
return;
|
||
}
|
||
|
||
if (!formData.start_date || !formData.start_time) {
|
||
setError('Укажите дату и время начала');
|
||
setLoading(false);
|
||
return;
|
||
}
|
||
|
||
if (!formData.price || formData.price <= 0) {
|
||
setError('Укажите стоимость занятия');
|
||
setLoading(false);
|
||
return;
|
||
}
|
||
|
||
// Объединяем дату и время в ISO строку
|
||
const startUtc = new Date(`${formData.start_date}T${formData.start_time}`).toISOString();
|
||
|
||
const payload: any = {
|
||
client: formData.client,
|
||
title: formData.title || generateTitle(
|
||
students.find(s => String(s.id) === formData.client) || null,
|
||
getSubjectName()
|
||
),
|
||
description: formData.description,
|
||
start_time: startUtc,
|
||
duration: formData.duration,
|
||
price: formData.price,
|
||
is_recurring: formData.is_recurring,
|
||
};
|
||
|
||
if (selectedSubjectId) {
|
||
payload.subject_id = selectedSubjectId;
|
||
} else if (selectedMentorSubjectId) {
|
||
payload.mentor_subject_id = selectedMentorSubjectId;
|
||
} else if (customSubjectName) {
|
||
payload.subject_name = customSubjectName;
|
||
}
|
||
|
||
await createLesson(payload);
|
||
|
||
// Сброс формы
|
||
setFormData({
|
||
client: '',
|
||
title: '',
|
||
description: '',
|
||
start_date: '',
|
||
start_time: '',
|
||
duration: 60,
|
||
price: undefined,
|
||
is_recurring: false,
|
||
});
|
||
setSelectedSubjectId(null);
|
||
setSelectedMentorSubjectId(null);
|
||
setCustomSubjectName('');
|
||
|
||
onSuccess();
|
||
onClose();
|
||
} catch (err: any) {
|
||
console.error('[CreateLessonDialog] Ошибка создания занятия:', err);
|
||
if (err.response?.data) {
|
||
const fieldErrors = Object.entries(err.response.data)
|
||
.map(([key, value]) => `${key}: ${Array.isArray(value) ? value.join(', ') : value}`)
|
||
.join('\n');
|
||
setError(fieldErrors);
|
||
} else {
|
||
setError(err.message || 'Ошибка создания занятия');
|
||
}
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
const handleClose = () => {
|
||
if (!loading) {
|
||
setFormData({
|
||
client: '',
|
||
title: '',
|
||
description: '',
|
||
start_date: '',
|
||
start_time: '',
|
||
duration: 60,
|
||
price: undefined,
|
||
is_recurring: false,
|
||
});
|
||
setSelectedSubjectId(null);
|
||
setSelectedMentorSubjectId(null);
|
||
setCustomSubjectName('');
|
||
setError(null);
|
||
onClose();
|
||
}
|
||
};
|
||
|
||
if (!open || !componentsLoaded) return null;
|
||
|
||
return (
|
||
<>
|
||
<md-dialog
|
||
open={open}
|
||
onCancel={handleClose}
|
||
style={{
|
||
'--md-dialog-container-color': 'var(--md-sys-color-surface)',
|
||
'--md-dialog-headline-color': 'var(--md-sys-color-on-surface)',
|
||
'--md-dialog-supporting-text-color': 'var(--md-sys-color-on-surface-variant)',
|
||
} as React.CSSProperties}
|
||
>
|
||
<div slot="headline">Создать занятие</div>
|
||
|
||
<form slot="content" method="dialog" onSubmit={(e) => { e.preventDefault(); handleSubmit(e); }} style={{ display: 'flex', flexDirection: 'column', gap: '20px', minWidth: '500px', maxWidth: '600px' }}>
|
||
{error && (
|
||
<div style={{
|
||
padding: '12px',
|
||
borderRadius: '8px',
|
||
background: 'var(--md-sys-color-error-container)',
|
||
color: 'var(--md-sys-color-on-error-container)',
|
||
fontSize: '14px',
|
||
whiteSpace: 'pre-wrap',
|
||
}}>
|
||
{error}
|
||
</div>
|
||
)}
|
||
|
||
{/* Ученик */}
|
||
<div>
|
||
<label style={{
|
||
display: 'block',
|
||
fontSize: '14px',
|
||
fontWeight: '500',
|
||
color: 'var(--md-sys-color-on-surface)',
|
||
marginBottom: '8px',
|
||
}}>
|
||
Ученик *
|
||
</label>
|
||
<md-outlined-field label="Выберите ученика" style={{ width: '100%' }}>
|
||
<select
|
||
slot="input"
|
||
value={formData.client}
|
||
onChange={(e) => setFormData(prev => ({ ...prev, client: e.target.value }))}
|
||
required
|
||
disabled={loading}
|
||
style={{
|
||
border: 'none',
|
||
outline: 'none',
|
||
background: 'transparent',
|
||
width: '100%',
|
||
fontSize: '16px',
|
||
color: 'var(--md-sys-color-on-surface)',
|
||
fontFamily: 'inherit',
|
||
cursor: loading ? 'not-allowed' : 'pointer',
|
||
}}
|
||
>
|
||
<option value="">Выберите ученика</option>
|
||
{students.map(student => (
|
||
<option key={student.id} value={String(student.id)}>
|
||
{`${student.user?.first_name || ''} ${student.user?.last_name || ''}`.trim() || student.user?.email || ''}
|
||
</option>
|
||
))}
|
||
</select>
|
||
</md-outlined-field>
|
||
</div>
|
||
|
||
{/* Предмет */}
|
||
<div>
|
||
<label style={{
|
||
display: 'block',
|
||
fontSize: '14px',
|
||
fontWeight: '500',
|
||
color: 'var(--md-sys-color-on-surface)',
|
||
marginBottom: '8px',
|
||
}}>
|
||
Предмет *
|
||
</label>
|
||
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
|
||
<md-outlined-field label="Выберите предмет" style={{ width: '100%' }}>
|
||
<select
|
||
slot="input"
|
||
value={selectedSubjectId ? String(selectedSubjectId) : selectedMentorSubjectId ? String(selectedMentorSubjectId) : ''}
|
||
onChange={(e: any) => {
|
||
const value = e.target.value;
|
||
if (value) {
|
||
handleSubjectChange(Number(value), false);
|
||
} else {
|
||
handleSubjectChange(null, false);
|
||
}
|
||
}}
|
||
disabled={loading}
|
||
style={{
|
||
border: 'none',
|
||
outline: 'none',
|
||
background: 'transparent',
|
||
width: '100%',
|
||
fontSize: '16px',
|
||
color: 'var(--md-sys-color-on-surface)',
|
||
fontFamily: 'inherit',
|
||
cursor: loading ? 'not-allowed' : 'pointer',
|
||
}}
|
||
>
|
||
<option value="">Выберите предмет</option>
|
||
{subjects.map(subject => (
|
||
<option key={subject.id} value={String(subject.id)}>
|
||
{subject.name}
|
||
</option>
|
||
))}
|
||
{mentorSubjects.map(subject => (
|
||
<option key={subject.id} value={String(subject.id)}>
|
||
{subject.name}
|
||
</option>
|
||
))}
|
||
</select>
|
||
</md-outlined-field>
|
||
|
||
<md-outlined-field label="Или введите свой предмет" style={{ width: '100%' }}>
|
||
<input
|
||
slot="input"
|
||
type="text"
|
||
value={customSubjectName}
|
||
onChange={(e) => {
|
||
setCustomSubjectName(e.target.value);
|
||
if (e.target.value) {
|
||
handleSubjectChange(null, true, e.target.value);
|
||
} else {
|
||
handleSubjectChange(null, false);
|
||
}
|
||
}}
|
||
placeholder="Название предмета"
|
||
disabled={loading}
|
||
style={{
|
||
border: 'none',
|
||
outline: 'none',
|
||
background: 'transparent',
|
||
width: '100%',
|
||
fontSize: '16px',
|
||
color: 'var(--md-sys-color-on-surface)',
|
||
}}
|
||
/>
|
||
</md-outlined-field>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Название */}
|
||
<div>
|
||
<label style={{
|
||
display: 'block',
|
||
fontSize: '14px',
|
||
fontWeight: '500',
|
||
color: 'var(--md-sys-color-on-surface)',
|
||
marginBottom: '8px',
|
||
}}>
|
||
Название занятия
|
||
</label>
|
||
<md-outlined-field label="Название" style={{ width: '100%' }}>
|
||
<input
|
||
slot="input"
|
||
type="text"
|
||
value={formData.title}
|
||
onChange={(e) => setFormData(prev => ({ ...prev, title: e.target.value }))}
|
||
placeholder="Автоматически генерируется"
|
||
disabled={loading}
|
||
style={{
|
||
border: 'none',
|
||
outline: 'none',
|
||
background: 'transparent',
|
||
width: '100%',
|
||
fontSize: '16px',
|
||
color: 'var(--md-sys-color-on-surface)',
|
||
}}
|
||
/>
|
||
</md-outlined-field>
|
||
</div>
|
||
|
||
{/* Описание */}
|
||
<div>
|
||
<label style={{
|
||
display: 'block',
|
||
fontSize: '14px',
|
||
fontWeight: '500',
|
||
color: 'var(--md-sys-color-on-surface)',
|
||
marginBottom: '8px',
|
||
}}>
|
||
Описание
|
||
</label>
|
||
<md-outlined-field label="Описание" style={{ width: '100%' }}>
|
||
<textarea
|
||
slot="input"
|
||
value={formData.description}
|
||
onChange={(e) => setFormData(prev => ({ ...prev, description: e.target.value }))}
|
||
placeholder="Дополнительная информация о занятии"
|
||
disabled={loading}
|
||
rows={3}
|
||
style={{
|
||
border: 'none',
|
||
outline: 'none',
|
||
background: 'transparent',
|
||
width: '100%',
|
||
fontSize: '16px',
|
||
color: 'var(--md-sys-color-on-surface)',
|
||
resize: 'vertical',
|
||
fontFamily: 'inherit',
|
||
}}
|
||
/>
|
||
</md-outlined-field>
|
||
</div>
|
||
|
||
{/* Дата начала */}
|
||
<div>
|
||
<label style={{
|
||
display: 'block',
|
||
fontSize: '14px',
|
||
fontWeight: '500',
|
||
color: 'var(--md-sys-color-on-surface)',
|
||
marginBottom: '8px',
|
||
}}>
|
||
Дата начала *
|
||
</label>
|
||
<md-outlined-field label="Дата" style={{ width: '100%' }}>
|
||
<input
|
||
slot="input"
|
||
type="date"
|
||
value={formData.start_date}
|
||
onChange={(e) => handleDateChange(e.target.value)}
|
||
required
|
||
disabled={loading}
|
||
style={{
|
||
border: 'none',
|
||
outline: 'none',
|
||
background: 'transparent',
|
||
width: '100%',
|
||
fontSize: '16px',
|
||
color: 'var(--md-sys-color-on-surface)',
|
||
fontFamily: 'inherit',
|
||
}}
|
||
/>
|
||
</md-outlined-field>
|
||
</div>
|
||
|
||
{/* Время начала и длительность */}
|
||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px' }}>
|
||
<div>
|
||
<label style={{
|
||
display: 'block',
|
||
fontSize: '14px',
|
||
fontWeight: '500',
|
||
color: 'var(--md-sys-color-on-surface)',
|
||
marginBottom: '8px',
|
||
}}>
|
||
Время начала *
|
||
</label>
|
||
<md-outlined-field label="Время" style={{ width: '100%' }}>
|
||
<input
|
||
slot="input"
|
||
type="time"
|
||
value={formData.start_time}
|
||
onChange={(e) => handleTimeChange(e.target.value)}
|
||
required
|
||
disabled={loading}
|
||
style={{
|
||
border: 'none',
|
||
outline: 'none',
|
||
background: 'transparent',
|
||
width: '100%',
|
||
fontSize: '16px',
|
||
color: 'var(--md-sys-color-on-surface)',
|
||
fontFamily: 'inherit',
|
||
}}
|
||
/>
|
||
</md-outlined-field>
|
||
</div>
|
||
|
||
<div>
|
||
<label style={{
|
||
display: 'block',
|
||
fontSize: '14px',
|
||
fontWeight: '500',
|
||
color: 'var(--md-sys-color-on-surface)',
|
||
marginBottom: '8px',
|
||
}}>
|
||
Длительность (минуты) *
|
||
</label>
|
||
<md-outlined-field label="Длительность" style={{ width: '100%' }}>
|
||
<select
|
||
slot="input"
|
||
value={formData.duration}
|
||
onChange={(e) => handleDurationChange(Number(e.target.value))}
|
||
required
|
||
disabled={loading}
|
||
style={{
|
||
border: 'none',
|
||
outline: 'none',
|
||
background: 'transparent',
|
||
width: '100%',
|
||
fontSize: '16px',
|
||
color: 'var(--md-sys-color-on-surface)',
|
||
fontFamily: 'inherit',
|
||
cursor: loading ? 'not-allowed' : 'pointer',
|
||
}}
|
||
>
|
||
<option value={30}>30 минут</option>
|
||
<option value={45}>45 минут</option>
|
||
<option value={60}>1 час</option>
|
||
<option value={90}>1.5 часа</option>
|
||
<option value={120}>2 часа</option>
|
||
</select>
|
||
</md-outlined-field>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Цена */}
|
||
<div>
|
||
<label style={{
|
||
display: 'block',
|
||
fontSize: '14px',
|
||
fontWeight: '500',
|
||
color: 'var(--md-sys-color-on-surface)',
|
||
marginBottom: '8px',
|
||
}}>
|
||
Стоимость (₽) *
|
||
</label>
|
||
<md-outlined-field label="Стоимость" style={{ width: '100%' }}>
|
||
<input
|
||
slot="input"
|
||
type="number"
|
||
value={formData.price || ''}
|
||
onChange={(e) => setFormData(prev => ({ ...prev, price: Number(e.target.value) }))}
|
||
required
|
||
min={0}
|
||
step={100}
|
||
disabled={loading}
|
||
style={{
|
||
border: 'none',
|
||
outline: 'none',
|
||
background: 'transparent',
|
||
width: '100%',
|
||
fontSize: '16px',
|
||
color: 'var(--md-sys-color-on-surface)',
|
||
}}
|
||
/>
|
||
</md-outlined-field>
|
||
</div>
|
||
|
||
{/* Постоянное занятие */}
|
||
<div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
|
||
<md-switch
|
||
checked={formData.is_recurring}
|
||
onInput={(e: any) => setFormData(prev => ({ ...prev, is_recurring: e.target.checked }))}
|
||
disabled={loading}
|
||
/>
|
||
<label style={{
|
||
fontSize: '14px',
|
||
color: 'var(--md-sys-color-on-surface)',
|
||
cursor: 'pointer',
|
||
}}>
|
||
Постоянное занятие (повторяется еженедельно)
|
||
</label>
|
||
</div>
|
||
</form>
|
||
|
||
<div slot="actions">
|
||
<md-text-button onClick={handleClose} disabled={loading}>
|
||
Отмена
|
||
</md-text-button>
|
||
<md-filled-button onClick={(e) => { e.preventDefault(); handleSubmit(e); }} disabled={loading}>
|
||
{loading ? 'Создание...' : 'Создать'}
|
||
</md-filled-button>
|
||
</div>
|
||
</md-dialog>
|
||
<style jsx global>{`
|
||
md-dialog {
|
||
--md-dialog-container-shape: 28px;
|
||
--md-dialog-container-max-width: 600px;
|
||
--md-dialog-container-min-width: 500px;
|
||
}
|
||
|
||
md-dialog::part(container) {
|
||
margin: auto;
|
||
position: fixed;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
max-height: 90vh;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
md-dialog form {
|
||
padding: 24px;
|
||
}
|
||
|
||
md-dialog [slot="actions"] {
|
||
display: flex;
|
||
gap: 8px;
|
||
justify-content: flex-end;
|
||
padding: 8px 24px 24px 24px;
|
||
}
|
||
|
||
md-outlined-field {
|
||
width: 100%;
|
||
}
|
||
|
||
md-outlined-field input[type="date"],
|
||
md-outlined-field input[type="time"] {
|
||
font-family: inherit;
|
||
font-size: 16px;
|
||
color: var(--md-sys-color-on-surface);
|
||
}
|
||
|
||
md-outlined-field input[type="date"]::-webkit-calendar-picker-indicator,
|
||
md-outlined-field input[type="time"]::-webkit-calendar-picker-indicator {
|
||
cursor: pointer;
|
||
opacity: 0.6;
|
||
}
|
||
|
||
md-outlined-field input[type="date"]::-webkit-calendar-picker-indicator:hover,
|
||
md-outlined-field input[type="time"]::-webkit-calendar-picker-indicator:hover {
|
||
opacity: 1;
|
||
}
|
||
`}</style>
|
||
</>
|
||
);
|
||
};
|