base commit

This commit is contained in:
@kirill.komarov
2026-05-10 13:50:44 +05:00
parent 6c07488964
commit 97537a8717
22 changed files with 307 additions and 100 deletions
@@ -14,6 +14,7 @@ import { Link as RouterLink } from 'react-router-dom'
import { fetchMyOrder, postOrderMessage } from '@/entities/order/api/order-api'
import { fetchMyConversations, markOrderMessagesRead } from '@/entities/user/api/messages-api'
import { orderStatusLabelRu } from '@/shared/lib/order-status-labels'
import { ChatMessageBubble } from '@/shared/ui/ChatMessageBubble'
import { RichTextMessageContent } from '@/shared/ui/RichTextMessageContent'
import { RichTextMessageEditor } from '@/shared/ui/RichTextMessageEditor'
@@ -114,13 +115,15 @@ export function MessagesPage() {
</Typography>
</Stack>
}
secondaryTypographyProps={{
sx: {
mt: 0.5,
overflow: 'hidden',
display: '-webkit-box',
WebkitLineClamp: 2,
WebkitBoxOrient: 'vertical',
slotProps={{
secondary: {
sx: {
mt: 0.5,
overflow: 'hidden',
display: '-webkit-box',
WebkitLineClamp: 2,
WebkitBoxOrient: 'vertical',
},
},
}}
secondary={c.preview}
@@ -160,24 +163,12 @@ export function MessagesPage() {
</Stack>
<Stack spacing={1} sx={{ mb: 2, maxHeight: 360, overflow: 'auto' }}>
{order.messages.map((m) => (
<Box
key={m.id}
sx={{
p: 1.25,
borderRadius: 2,
bgcolor: m.authorType === 'admin' ? 'grey.100' : 'primary.50',
border: 1,
borderColor: 'divider',
alignSelf: m.authorType === 'admin' ? 'flex-start' : 'flex-end',
width: 'fit-content',
maxWidth: '85%',
}}
>
<ChatMessageBubble key={m.id} authorType={m.authorType === 'admin' ? 'admin' : 'user'}>
<Typography variant="caption" color="text.secondary">
{m.authorType === 'admin' ? 'Админ' : 'Вы'} · {new Date(m.createdAt).toLocaleString()}
</Typography>
<RichTextMessageContent value={m.text} tone="chat" />
</Box>
</ChatMessageBubble>
))}
{order.messages.length === 0 && <Typography color="text.secondary">Нет сообщений.</Typography>}
</Stack>
@@ -7,6 +7,7 @@ import DialogActions from '@mui/material/DialogActions'
import DialogContent from '@mui/material/DialogContent'
import DialogTitle from '@mui/material/DialogTitle'
import Divider from '@mui/material/Divider'
import Link from '@mui/material/Link'
import Rating from '@mui/material/Rating'
import Stack from '@mui/material/Stack'
import Typography from '@mui/material/Typography'
@@ -22,8 +23,10 @@ import {
} from '@/entities/order/api/order-api'
import { postProductReview, uploadReviewImage } from '@/entities/product/api/reviews-api'
import { markOrderMessagesRead } from '@/entities/user/api/messages-api'
import { PICKUP_ADDRESS_FULL } from '@/shared/constants/pickup-point'
import { formatPriceRub } from '@/shared/lib/format-price'
import { orderStatusLabelRu } from '@/shared/lib/order-status-labels'
import { ChatMessageBubble } from '@/shared/ui/ChatMessageBubble'
import { RichTextMessageContent } from '@/shared/ui/RichTextMessageContent'
import { RichTextMessageEditor } from '@/shared/ui/RichTextMessageEditor'
@@ -96,6 +99,7 @@ export function OrderDetailPage() {
})
const order = orderQuery.data?.item
const payOnPickup = (order?.paymentMethod ?? 'online') === 'on_pickup'
const canSendMessage = text.replace(/<[^>]*>/g, ' ').trim().length > 0
const eligibilityQuery = useQuery({
@@ -199,6 +203,7 @@ export function OrderDetailPage() {
</Typography>
<Typography color="text.secondary" variant="body2" sx={{ mb: 1 }}>
Способ: {order.deliveryType === 'pickup' ? 'Самовывоз' : 'Доставка'}
{order.deliveryType === 'pickup' && <> · оплата: {payOnPickup ? 'при получении' : 'онлайн'}</>}
</Typography>
{order.deliveryType === 'delivery' && (
<>
@@ -220,9 +225,21 @@ export function OrderDetailPage() {
</>
)}
{order.deliveryType === 'pickup' && (
<Typography color="text.secondary">
Адрес доставки не требуется. Мы свяжемся для согласования самовывоза.
</Typography>
<Stack spacing={0.75}>
<Typography color="text.secondary" variant="body2">
Адрес самовывоза и карта на странице{' '}
<Link component={RouterLink} to="/about" underline="hover">
О нас
</Link>
.
</Typography>
<Typography variant="body2" sx={{ fontWeight: 600 }}>
{PICKUP_ADDRESS_FULL}
</Typography>
<Typography color="text.secondary" variant="body2">
Заберите заказ точно ко времени, которое согласуем по телефону или в чате заказа.
</Typography>
</Stack>
)}
{order.comment && (
<Typography color="text.secondary" variant="body2" sx={{ mt: 1 }}>
@@ -235,25 +252,33 @@ export function OrderDetailPage() {
<Typography variant="h6" gutterBottom>
Оплата
</Typography>
{order.status === 'PENDING_PAYMENT' && (
<>
<Typography color="text.secondary" variant="body2" sx={{ mb: 1 }}>
Пока это заглушка. После нажатия заказ перейдёт в статус «Проверка оплаты».
</Typography>
<Button variant="contained" onClick={() => payMut.mutate()} disabled={payMut.isPending}>
Оплатить (заглушка)
</Button>
</>
)}
{order.status === 'PAYMENT_VERIFICATION' && (
<Typography color="info.main" variant="body2">
Оплата отправлена на проверку. Мы проверим поступление и обновим статус.
</Typography>
)}
{!['PENDING_PAYMENT', 'PAYMENT_VERIFICATION'].includes(order.status) && (
{payOnPickup ? (
<Typography color="text.secondary" variant="body2">
На этом этапе действий по оплате в этом блоке не требуется.
Оплата при получении на точке самовывоза (наличные или карта по договорённости).
</Typography>
) : (
<>
{order.status === 'PENDING_PAYMENT' && (
<>
<Typography color="text.secondary" variant="body2" sx={{ mb: 1 }}>
Пока это заглушка. После нажатия заказ перейдёт в статус «Проверка оплаты».
</Typography>
<Button variant="contained" onClick={() => payMut.mutate()} disabled={payMut.isPending}>
Оплатить (заглушка)
</Button>
</>
)}
{order.status === 'PAYMENT_VERIFICATION' && (
<Typography color="info.main" variant="body2">
Оплата отправлена на проверку. Мы проверим поступление и обновим статус.
</Typography>
)}
{!['PENDING_PAYMENT', 'PAYMENT_VERIFICATION'].includes(order.status) && (
<Typography color="text.secondary" variant="body2">
На этом этапе действий по оплате в этом блоке не требуется.
</Typography>
)}
</>
)}
</Box>
@@ -316,24 +341,12 @@ export function OrderDetailPage() {
</Typography>
<Stack spacing={1} sx={{ mb: 2 }}>
{order.messages.map((m) => (
<Box
key={m.id}
sx={{
p: 1.25,
borderRadius: 2,
bgcolor: m.authorType === 'admin' ? 'grey.100' : 'primary.50',
border: 1,
borderColor: 'divider',
alignSelf: m.authorType === 'admin' ? 'flex-start' : 'flex-end',
width: 'fit-content',
maxWidth: '85%',
}}
>
<ChatMessageBubble key={m.id} authorType={m.authorType === 'admin' ? 'admin' : 'user'}>
<Typography variant="caption" color="text.secondary">
{m.authorType === 'admin' ? 'Админ' : 'Вы'} · {new Date(m.createdAt).toLocaleString()}
</Typography>
<RichTextMessageContent value={m.text} tone="chat" />
</Box>
</ChatMessageBubble>
))}
{order.messages.length === 0 && <Typography color="text.secondary">Пока сообщений нет.</Typography>}
</Stack>