feat:日历滑动
This commit is contained in:
parent
55cfe79dab
commit
69a1bd0de3
|
@ -19,6 +19,7 @@
|
|||
"node-gyp": "^9.3.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-infinite-scroll-component": "^6.1.0",
|
||||
"react-router-dom": "^6.6.2",
|
||||
"react-scripts": "5.0.1",
|
||||
"react-virtualized": "^9.22.3",
|
||||
|
@ -14160,6 +14161,17 @@
|
|||
"resolved": "https://registry.npmmirror.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
|
||||
"integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="
|
||||
},
|
||||
"node_modules/react-infinite-scroll-component": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/react-infinite-scroll-component/-/react-infinite-scroll-component-6.1.0.tgz",
|
||||
"integrity": "sha512-SQu5nCqy8DxQWpnUVLx7V7b7LcA37aM7tvoWjTLZp1dk6EJibM5/4EJKzOnl07/BsM1Y40sKLuqjCwwH/xV0TQ==",
|
||||
"dependencies": {
|
||||
"throttle-debounce": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/react-is/-/react-is-17.0.2.tgz",
|
||||
|
@ -15757,6 +15769,14 @@
|
|||
"resolved": "https://registry.npmmirror.com/throat/-/throat-6.0.2.tgz",
|
||||
"integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ=="
|
||||
},
|
||||
"node_modules/throttle-debounce": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-2.3.0.tgz",
|
||||
"integrity": "sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/thunky": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/thunky/-/thunky-1.1.0.tgz",
|
||||
|
@ -27773,6 +27793,14 @@
|
|||
"resolved": "https://registry.npmmirror.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
|
||||
"integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="
|
||||
},
|
||||
"react-infinite-scroll-component": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/react-infinite-scroll-component/-/react-infinite-scroll-component-6.1.0.tgz",
|
||||
"integrity": "sha512-SQu5nCqy8DxQWpnUVLx7V7b7LcA37aM7tvoWjTLZp1dk6EJibM5/4EJKzOnl07/BsM1Y40sKLuqjCwwH/xV0TQ==",
|
||||
"requires": {
|
||||
"throttle-debounce": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/react-is/-/react-is-17.0.2.tgz",
|
||||
|
@ -29019,6 +29047,11 @@
|
|||
"resolved": "https://registry.npmmirror.com/throat/-/throat-6.0.2.tgz",
|
||||
"integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ=="
|
||||
},
|
||||
"throttle-debounce": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-2.3.0.tgz",
|
||||
"integrity": "sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ=="
|
||||
},
|
||||
"thunky": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/thunky/-/thunky-1.1.0.tgz",
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
"node-gyp": "^9.3.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-infinite-scroll-component": "^6.1.0",
|
||||
"react-router-dom": "^6.6.2",
|
||||
"react-scripts": "5.0.1",
|
||||
"react-virtualized": "^9.22.3",
|
||||
|
|
|
@ -8,3 +8,18 @@ export const addTaskLog = (taskLog) => {
|
|||
export const listTaskLog = (request) => {
|
||||
return requestUtil.get('/todo-server/V2/search/task_message_diary?search=' + encodeURI(request));
|
||||
}
|
||||
|
||||
export const updateTaskLogEnableById = (enableFlag, id) => {
|
||||
let request = {
|
||||
"updateColumnList": [{"name": "enableFlag", "value": enableFlag, "operateType": "="}],
|
||||
"conditionColumnList": [{"name": "id", "value": id, "operateType": "="}]
|
||||
}
|
||||
return requestUtil.put('/todo-server/search/task_message_diary', request);
|
||||
}
|
||||
export const deleteTaskLogById = (id) => {
|
||||
let request = {
|
||||
"updateColumnList": [{"name": "deleteFlag", "value": "1", "operateType": "="}],
|
||||
"conditionColumnList": [{"name": "id", "value": id, "operateType": "="}]
|
||||
}
|
||||
return requestUtil.put('/todo-server/search/task_message_diary', request);
|
||||
}
|
|
@ -23,7 +23,7 @@ const DetailForm = () => {
|
|||
const {setTitle, setRightDesc} = useOutletContext();
|
||||
const [currentPath, setCurrentPath] = React.useState("");
|
||||
const [updateFiledDisabled, setUpdateFiledDisabled] = React.useState(true);
|
||||
const [pName, setPName] = React.useState();
|
||||
const [pName, setPName] = React.useState("");
|
||||
const [pidArray, setPidArray] = React.useState([]);
|
||||
const [stateList, setStateList] = React.useState([]);
|
||||
const [priorityList, setPriorityList] = React.useState([]);
|
||||
|
@ -47,6 +47,18 @@ const DetailForm = () => {
|
|||
setCurrentPath("addTask");
|
||||
setUpdateFiledDisabled(false);
|
||||
setRightDesc(<Fragment/>)
|
||||
// 日志创建任务会传来pidArray和pName
|
||||
if (params.get('pidArray') && params.get('pName') && params.get('description')) {
|
||||
setPName(params.get('pName'));
|
||||
setPidArray(params.get('pidArray').split(','))
|
||||
form.setFieldValue("pidArray", params.get('pidArray').split(','))
|
||||
form.setFieldValue("description", params.get('description'))
|
||||
if (params.get('description').length>5){
|
||||
form.setFieldValue("name", params.get('description').substring(0,5))
|
||||
}else {
|
||||
form.setFieldValue("description", params.get('description'))
|
||||
}
|
||||
}
|
||||
} else if (location.pathname.endsWith("updateTask")) {
|
||||
setTitle("修改任务");
|
||||
setCurrentPath("updateTask");
|
||||
|
|
|
@ -1,11 +1,21 @@
|
|||
.log-task-detail{
|
||||
display: flex;
|
||||
.log-task-detail {
|
||||
height: calc(100vh - 45px);
|
||||
/* 确保子元素可以相对于此容器定位 */
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.log-send{
|
||||
|
||||
.log-detail {
|
||||
/*position: absolute;*/
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
max-height: calc(100vh - 140px);
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
.log-send {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
|
@ -15,12 +25,13 @@
|
|||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.log-send .send-button{
|
||||
.log-send .send-button {
|
||||
border-radius: 12px;
|
||||
width: 80px;
|
||||
height: 40px;
|
||||
}
|
||||
.detail-line{
|
||||
|
||||
.detail-line {
|
||||
border-radius: 6px;
|
||||
border: solid;
|
||||
width: auto;
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import {ActionSheet, Button, Dialog, Divider, Tabs, TextArea, Toast} from "antd-mobile";
|
||||
import {Fragment, useEffect, useMemo, useRef, useState} from "react";
|
||||
import React, {Fragment, useEffect, useMemo, useRef, useState} from "react";
|
||||
import "./index.css"
|
||||
import {useOutletContext, useSearchParams} from "react-router-dom";
|
||||
import {addTaskLog, listTaskLog} from "../../api/detailLogTaskApi";
|
||||
import {useNavigate, useOutletContext, useSearchParams} from "react-router-dom";
|
||||
import {addTaskLog, deleteTaskLogById, listTaskLog, updateTaskLogEnableById} from "../../api/detailLogTaskApi";
|
||||
import dayjs from "dayjs";
|
||||
import {copyTextToClipboard} from "../../utils/copyToClipBoard";
|
||||
import {getPTask} from "../../utils";
|
||||
import InfiniteScroll from "react-infinite-scroll-component";
|
||||
|
||||
export function DetailLogTask() {
|
||||
// 设置标题栏
|
||||
|
@ -14,114 +16,150 @@ export function DetailLogTask() {
|
|||
setRightDesc(<Fragment/>);
|
||||
}, [])
|
||||
let [params] = useSearchParams();
|
||||
// 路由
|
||||
const navigate = useNavigate();
|
||||
|
||||
// 发送展示日记
|
||||
const [currentShow, setCurrentShow] = useState('need');
|
||||
const textAreaRef = useRef(null);
|
||||
|
||||
const [taskLogList, setTaskLogList] = useState([]);
|
||||
const [sendValue, setSendValue] = useState('');
|
||||
|
||||
const [hasMore, setHasMore] = useState(true);
|
||||
const [pageTime, setPageTime] = useState(new Date());
|
||||
|
||||
// 记录上一次的滚动高度
|
||||
const previousScrollHeight = useRef(0);
|
||||
|
||||
// 点击操作面板
|
||||
const [actionSheetVisible, setActionSheetVisible] = useState(false)
|
||||
const [currentTask, setCurrentTask] = useState({});
|
||||
const [actions,setActions] = useState([
|
||||
{ text: '复制', key: 'copy' },
|
||||
{ text: '有效', key: 'need' },
|
||||
{ text: '创建任务', key: 'addTask'},
|
||||
{
|
||||
text: '删除',
|
||||
key: 'delete',
|
||||
onClick: async () => {
|
||||
const result = await Dialog.confirm({ content: '确定要删除吗?' })
|
||||
if (result) {
|
||||
Toast.show('执行了删除操作')
|
||||
}
|
||||
},
|
||||
},
|
||||
const [actions, setActions] = useState([
|
||||
{text: '复制', key: 'copy'},
|
||||
{text: '有效', key: 'need'},
|
||||
{text: '创建任务', key: 'addTask'},
|
||||
{text: '删除', key: 'delete'},
|
||||
]);
|
||||
|
||||
const taskLogMapMemory = useMemo(() => {
|
||||
return taskLogList.reduce((map, taskLog) => {
|
||||
if (!map.has(dayjs(taskLog.createdDate).format("YYYY-MM-DD"))) {
|
||||
map.set(dayjs(taskLog.createdDate).format("YYYY-MM-DD"), []);
|
||||
}
|
||||
map.get(dayjs(taskLog.createdDate).format("YYYY-MM-DD"))?.push(taskLog);
|
||||
return map;
|
||||
}, new Map());
|
||||
}, [taskLogList,currentShow])
|
||||
return taskLogList
|
||||
.filter(taskLog => {
|
||||
if (currentShow === 'all') {
|
||||
return true
|
||||
} else if (currentShow === 'need' && taskLog.enableFlag === '1') {
|
||||
return true
|
||||
} else return currentShow === 'noNeed' && taskLog.enableFlag === '0';
|
||||
})
|
||||
.reduce((map, taskLog) => {
|
||||
if (!map.has(dayjs(taskLog.createdDate).format("YYYY-MM-DD"))) {
|
||||
map.set(dayjs(taskLog.createdDate).format("YYYY-MM-DD"), []);
|
||||
}
|
||||
map.get(dayjs(taskLog.createdDate).format("YYYY-MM-DD"))?.push(taskLog);
|
||||
return map;
|
||||
}, new Map());
|
||||
}, [taskLogList, currentShow])
|
||||
const handleSend = () => {
|
||||
addTaskLog({
|
||||
"description": sendValue,
|
||||
"taskId": params.get('id'),
|
||||
"enableFlag": '1'
|
||||
}).then(res => {
|
||||
// 加入当前集合中
|
||||
setTaskLogList([...taskLogList,res]);
|
||||
setTaskLogList([...taskLogList, res]);
|
||||
})
|
||||
setSendValue('')
|
||||
textAreaRef.current.focus();
|
||||
};
|
||||
useEffect(() => {
|
||||
textAreaRef.current.focus();
|
||||
|
||||
async function fetchMessages() {
|
||||
// 获取之前的日志信息,根据日期分组排序,遍历map
|
||||
listTaskLog(`{
|
||||
"sortList":[{"direction":"DESC","property":"createdDate"}],
|
||||
const res = await listTaskLog(JSON.stringify({
|
||||
"pageSize": 20,
|
||||
"sortList": [{"direction": "DESC", "property": "createdDate"}],
|
||||
"data": {
|
||||
"andList":[{
|
||||
"name":"taskId",
|
||||
"operateType":"=",
|
||||
"value":"${params.get('id')}"
|
||||
"andList": [{
|
||||
"name": "taskId",
|
||||
"operateType": "=",
|
||||
"value": params.get('id')
|
||||
}, {
|
||||
"name": "createdDate",
|
||||
"operateType": "<",
|
||||
"value": pageTime
|
||||
}]
|
||||
}
|
||||
}`).then(res => {
|
||||
console.log({res})
|
||||
if (res.content.length > 0) {
|
||||
setTaskLogList(res.content.reverse());
|
||||
// setTaskLogMap(res.content.reduce((map, taskLog) => {
|
||||
// if (!map.has(dayjs(taskLog.createdDate).format("YYYY-MM-DD"))) {
|
||||
// map.set(dayjs(taskLog.createdDate).format("YYYY-MM-DD"), []);
|
||||
// }
|
||||
// map.get(dayjs(taskLog.createdDate).format("YYYY-MM-DD"))?.push(taskLog);
|
||||
// return map;
|
||||
// }, new Map()));
|
||||
}
|
||||
})
|
||||
}))
|
||||
console.log({res})
|
||||
if (res.content.length > 0) {
|
||||
setPageTime(res.content[res.content.length - 1].createdDate)
|
||||
setTaskLogList([...taskLogList, ...res.content]);
|
||||
} else if (res.page.totalElements === 0) {
|
||||
setHasMore(false);
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setPageTime(new Date())
|
||||
textAreaRef.current.focus();
|
||||
fetchMessages()
|
||||
}, [])
|
||||
function NoNeed(){
|
||||
|
||||
function NoNeed() {
|
||||
return <s>失效</s>
|
||||
}
|
||||
|
||||
return <Fragment>
|
||||
<div className="log-task-detail">
|
||||
<div className="log-detail">
|
||||
<Tabs defaultActiveKey='need' onChange={(key)=>setCurrentShow(key)}>
|
||||
<Tabs.Tab title='全部' key='all' />
|
||||
<Tabs.Tab title='有效' key='need' />
|
||||
<Tabs.Tab key='noneed' title=<NoNeed/> />
|
||||
</Tabs>
|
||||
{
|
||||
Array.from(taskLogMapMemory.keys()).map(key => {
|
||||
return (<Fragment>
|
||||
{dayjs().isSame(dayjs(key), "date") ?
|
||||
<div key={key} style={{width: "100%", padding: "0 40px"}}>
|
||||
<Divider>今日</Divider>
|
||||
</div> :
|
||||
<div key={key} style={{width: "100%", padding: "0 20px"}}>
|
||||
<Divider>{key}</Divider>
|
||||
</div>}
|
||||
{taskLogMapMemory.get(key).map(taskLog => {
|
||||
return <div key={taskLog.id} style={{ display: 'flex', width: "80%", padding: "2px 20px"}}>
|
||||
<span className="detail-line" onClick={()=>{
|
||||
actions[1]={ text: '失效', key: 'noneed' }
|
||||
<Tabs defaultActiveKey='need' onChange={(key) => setCurrentShow(key)}>
|
||||
<Tabs.Tab title='全部' key='all'/>
|
||||
<Tabs.Tab title='有效' key='need'/>
|
||||
<Tabs.Tab key='noNeed' title=<NoNeed/> />
|
||||
</Tabs>
|
||||
<div id="scrollableDiv" className="log-detail"
|
||||
>
|
||||
<InfiniteScroll
|
||||
dataLength={taskLogList.length}
|
||||
next={fetchMessages}
|
||||
hasMore={hasMore}
|
||||
inverse={true} // 设置为 true 来反转列表的方向,使新消息在底部
|
||||
loader={<h4>加载中...</h4>}
|
||||
style={{display: 'flex', flexDirection: 'column-reverse'}}
|
||||
scrollableTarget="scrollableDiv"
|
||||
endMessage={
|
||||
<Divider>没有更久远的信息了</Divider>
|
||||
}
|
||||
>
|
||||
{
|
||||
Array.from(taskLogMapMemory.keys()).map(key => {
|
||||
return (<Fragment>
|
||||
{taskLogMapMemory.get(key).map(taskLog => {
|
||||
return <div key={taskLog.id}
|
||||
style={{display: 'flex', width: "80%", padding: "2px 20px"}}>
|
||||
<span className="detail-line" onClick={() => {
|
||||
if (taskLog.enableFlag === '0') {
|
||||
actions[1] = {text: '有效', key: 'need'}
|
||||
} else {
|
||||
actions[1] = {text: '失效', key: 'noNeed'}
|
||||
}
|
||||
// setActions([...actions])
|
||||
setCurrentTask(taskLog)
|
||||
setActionSheetVisible(true)
|
||||
}}>
|
||||
{taskLog.description}</span>
|
||||
</div>
|
||||
})}</Fragment>)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
})}
|
||||
{dayjs().isSame(dayjs(key), "date") ?
|
||||
<div key={key} style={{width: "100%", padding: "0 40px"}}>
|
||||
<Divider>今日</Divider>
|
||||
</div> :
|
||||
<div key={key} style={{width: "100%", padding: "0 20px"}}>
|
||||
<Divider>{key}</Divider>
|
||||
</div>}
|
||||
</Fragment>)
|
||||
})
|
||||
}
|
||||
</InfiniteScroll>
|
||||
</div>
|
||||
|
||||
<div className="log-send">
|
||||
<TextArea
|
||||
ref={(node) => {
|
||||
|
@ -133,6 +171,13 @@ export function DetailLogTask() {
|
|||
rows={1}
|
||||
autoSize={{minRows: 1, maxRows: 5}}
|
||||
maxLength={100}
|
||||
onKeyDown={event => {
|
||||
if (event.key === 'Enter') {
|
||||
handleSend();
|
||||
// 阻止换行符插入
|
||||
event.preventDefault();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
className="send-button"
|
||||
|
@ -148,6 +193,48 @@ export function DetailLogTask() {
|
|||
onAction={action => {
|
||||
if (action.key === 'copy') {
|
||||
copyTextToClipboard(currentTask.description)
|
||||
} else if (action.key === 'delete') {
|
||||
Dialog.confirm({
|
||||
content: '确定要删除吗?', onConfirm: () => {
|
||||
deleteTaskLogById(currentTask.id).then(result => {
|
||||
setTaskLogList(taskLogList.filter(log => log.id !== currentTask.id))
|
||||
})
|
||||
}
|
||||
})
|
||||
} else if (action.key === 'noNeed') {
|
||||
updateTaskLogEnableById('0', currentTask.id).then(result => {
|
||||
setTaskLogList(taskLogList.map(log => {
|
||||
if (log.id === currentTask.id) {
|
||||
log.enableFlag = '0'
|
||||
}
|
||||
return log;
|
||||
})
|
||||
)
|
||||
});
|
||||
} else if (action.key === 'need') {
|
||||
updateTaskLogEnableById('1', currentTask.id).then(result => {
|
||||
setTaskLogList(taskLogList.map(log => {
|
||||
if (log.id === currentTask.id) {
|
||||
log.enableFlag = '1'
|
||||
}
|
||||
return log;
|
||||
})
|
||||
)
|
||||
});
|
||||
} else if (action.key === 'addTask') {
|
||||
// 跳转到新增和新建下一条差不多,设置pidArray
|
||||
// 获取父任务信息
|
||||
Dialog.confirm({
|
||||
content: '确定要创建任务吗?', onConfirm: () => {
|
||||
getPTask(params.get('id')).then(res => {
|
||||
let parentMessageVOList = res[0].parentMessageVOList;
|
||||
console.log({res, parentMessageVOList});
|
||||
// 进入新增页面
|
||||
navigate(`/detail/addTask?
|
||||
pName=${parentMessageVOList[parentMessageVOList.length - 1].name}&pidArray=${parentMessageVOList.map(parent => parent.id).join(',')}&description=${currentTask.description}`)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
setActionSheetVisible(false)
|
||||
}}
|
||||
|
|
|
@ -232,7 +232,7 @@ const DetailSearchContext = () => {
|
|||
<CalendarPicker
|
||||
visible={visible}
|
||||
selectionMode='single'
|
||||
defaultDate={getFieldValue('todoDay')}
|
||||
defaultValue={getFieldValue('todoDay')??new Date()}
|
||||
onClose={() => {
|
||||
setVisible(false)
|
||||
}}
|
||||
|
|
|
@ -140,9 +140,12 @@ const ToDoList = () => {
|
|||
text: '删除',
|
||||
color: 'danger',
|
||||
onClick: async () => {
|
||||
await Dialog.confirm({
|
||||
const result = await Dialog.confirm({
|
||||
content: '确定要删除吗?',
|
||||
})
|
||||
if (result){
|
||||
await deleteTaskById(item.id)
|
||||
}
|
||||
// 关闭当前激活的 SwipeAction
|
||||
closeActiveSwipeAction();
|
||||
localRefresh()
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
.chat-window {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 80vh;
|
||||
width: 300px;
|
||||
margin: auto;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, .1);
|
||||
/*overflow:auto*/
|
||||
}
|
||||
|
||||
.messages-container {
|
||||
flex: 1;
|
||||
padding: 10px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.message {
|
||||
margin: 5px 0;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
max-width: 60%;
|
||||
}
|
||||
|
||||
.message.user {
|
||||
background-color: #d1e7dd;
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
.message.other {
|
||||
background-color: #f8d7da;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.input-area {
|
||||
display: flex;
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.input-area input {
|
||||
flex: 1;
|
||||
padding: 10px;
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.input-area button {
|
||||
padding: 10px;
|
||||
border: none;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.input-area button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
Loading…
Reference in New Issue