diff --git a/packages/app/src/components/PostCreator/index.jsx b/packages/app/src/components/PostCreator/index.jsx
index 679e3a05..3a5e7c79 100644
--- a/packages/app/src/components/PostCreator/index.jsx
+++ b/packages/app/src/components/PostCreator/index.jsx
@@ -3,96 +3,196 @@ import * as antd from "antd"
import { Icons } from "components/Icons"
import { User } from "models"
import classnames from "classnames"
+import { PostAdditions } from "components/PostCard"
import "./index.less"
+// TODO: Fetch `maxMessageLength` value from server API
const maxMessageLength = 512
-const PostCreatorInput = (props) => {
- const [value, setValue] = React.useState("")
+export default (props) => {
+ const api = window.app.request
- const canPublish = () => {
- return value.length !== 0 && value.length < maxMessageLength
- }
+ const [loading, setLoading] = React.useState(false)
+ const [uploaderVisible, setUploaderVisible] = React.useState(false)
+ const [focused, setFocused] = React.useState(false)
- const onChange = (e) => {
- setValue(e.target.value)
- }
+ const [userData, setUserData] = React.useState(null)
+ const [postData, setPostData] = React.useState({
+ message: "",
+ additions: []
+ })
- const handleSubmit = () => {
- if (canPublish()) {
- if (typeof props.onSubmit === "function") {
- props.onSubmit(value)
- }
-
- setValue("")
- }
- }
-
- return
-
-

-
-
-
-
-}
-
-export default class PostCreator extends React.Component {
- state = {
- loading: false,
- }
- api = window.app.request
-
- componentDidMount = async () => {
- const userData = await User.data()
-
- this.setState({
- userData
+ const updatePostData = (update) => {
+ setPostData({
+ ...postData,
+ ...update
})
}
- onSubmit = async (value) => {
- await this.setState({ loading: true })
+ const cleanPostData = () => {
+ setPostData({
+ message: "",
+ additions: []
+ })
+ }
- const result = this.api.put.post({
- message: value,
- }).catch(error => {
+ const submit = () => {
+ setLoading(true)
+
+ const response = api.put.post({ ...postData }).catch(error => {
console.error(error)
antd.message.error(error)
return false
})
- this.setState({ loading: false })
+ setLoading(false)
+
+ if (response) {
+ cleanPostData()
+ }
}
- render() {
- return
+ const onUploadFile = async (req) => {
+ // get file data
+ const file = req.file
+
+ // append to form data
+ const formData = new FormData()
+ formData.append("files", file)
+
+ setLoading(true)
+
+ // send request
+ const request = await api.post.upload(formData, undefined).catch((error) => {
+ console.error(error)
+ antd.message.error(error)
+
+ req.onError(error)
+
+ return false
+ })
+
+ setLoading(false)
+
+ if (request) {
+ return req.onSuccess(request)
+ }
}
+
+ const canPublish = () => {
+ const messageLengthValid = postData.message.length !== 0 && postData.message.length < maxMessageLength
+
+ return Boolean(messageLengthValid)
+ }
+
+ const onDraggerChange = (change) => {
+ console.log(change)
+
+ switch (change.file.status) {
+ case "done": {
+ let additions = postData.additions ?? []
+
+ additions.push(...change.file.response)
+
+ return updatePostData({ additions })
+ }
+
+ default: {
+ break
+ }
+ }
+ }
+
+ const onChangeMessageInput = (event) => {
+ console.log(event.target.value)
+
+ updatePostData({
+ message: event.target.value
+ })
+ }
+
+ const toggleUploader = (to) => {
+ setUploaderVisible(to ?? !uploaderVisible)
+ }
+
+ const toggleFocus = (to) => {
+ setFocused(to ?? !focused)
+ }
+
+ React.useEffect(() => {
+ User.data().then(user => {
+ setUserData(user)
+ })
+ }, [])
+
+ return {
+ e.preventDefault()
+ toggleUploader(true)
+ }}
+ onDragLeave={(e) => {
+ e.preventDefault()
+ toggleUploader(false)
+ }}
+ onMouseEnter={() => {
+ toggleFocus(true)
+ }}
+ onMouseLeave={() => {
+ toggleFocus(false)
+ }}
+ >
+
+
+

+
+
+
+
+
+ {postData.additions.length > 0 &&
}
+
+
+
+
{
+ toggleUploader()
+ }}
+ icon={}
+ />
+
+
+
+
+
+ Click or drag file to this area to upload
+
+
+
}
\ No newline at end of file
diff --git a/packages/app/src/components/PostCreator/index.less b/packages/app/src/components/PostCreator/index.less
index 9a5439fe..dbd506ac 100644
--- a/packages/app/src/components/PostCreator/index.less
+++ b/packages/app/src/components/PostCreator/index.less
@@ -1,15 +1,199 @@
.postCreator {
- width : 100%;
- padding : 15px;
+ display: flex;
+ flex-direction: column;
+
+ width: 100%;
+ padding: 15px;
background-color: var(--background-color-accent);
- max-width : 600px;
+ max-width: 600px;
border-radius: 7px;
+ .additions {
+ margin: 10px 0;
+ width: 100%;
+ height: 28vh;
+
+ .slick-slider {
+ .slick-prev {
+ display: inline !important;
+ color: #ffffff;
+
+ z-index: 100;
+
+ top: 0;
+ left: 0;
+
+ height: 100%;
+ width: 5vw;
+
+ opacity: 0;
+
+ transition: all 150ms ease-in-out;
+
+ &:hover {
+ opacity: 0.6;
+ width: 7vw;
+ }
+
+ &:active {
+ transform: scale(0.5);
+ }
+ }
+
+ .slick-next {
+ display: inline !important;
+ color: #ffffff;
+
+ z-index: 100;
+
+ top: 0;
+ right: 0;
+
+ height: 100%;
+ width: 5vw;
+
+ opacity: 0;
+
+ transition: all 150ms ease-in-out;
+
+ &:hover {
+ opacity: 0.6;
+ width: 7vw;
+ }
+
+ &:active {
+ transform: scale(0.5);
+ }
+ }
+ }
+
+ .slick-track {
+ display: flex;
+ align-items: center;
+ }
+
+ .slick-slide {
+ height: 100%;
+
+ div {
+ height: 100%;
+ }
+ }
+
+ .slick-list {
+ border-radius: 8px;
+ }
+
+ .ant-carousel,
+ .slick-slider,
+ .slick-list,
+ .slick-track {
+ height: 100%;
+ }
+
+ .addition {
+ width: 100%;
+ height: 100%;
+
+ // fixtures for media content
+ img {
+ width: 100%;
+ height: 100%;
+
+ user-select: none;
+ -webkit-user-drag: none;
+
+ object-fit: cover;
+ }
+
+ video {
+ width: 100%;
+ height: 100%;
+
+ user-select: none;
+ -webkit-user-drag: none;
+
+ object-fit: cover;
+ }
+
+ audio {
+ width: 100%;
+ height: 100%;
+
+ user-select: none;
+ -webkit-user-drag: none;
+ }
+
+ >div {
+ height: 100%;
+ }
+ }
+ }
+
+ .actions {
+ display: inline-flex;
+ flex-direction: row;
+ justify-content: flex-start;
+
+ height: 40px;
+
+ overflow: hidden;
+
+ transition: all 150ms ease-in-out;
+
+ >div {
+ margin-left: 10px;
+ font-size: 1rem;
+
+ svg {
+ margin: 0 !important;
+ }
+ }
+
+ &.hided {
+ height: 0;
+ }
+ }
+
+ .uploader {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+
+ height: 5vh;
+ width: 100%;
+
+ overflow: hidden;
+
+ transition: all 150ms ease-in-out;
+
+ >div {
+ margin-left: 10px;
+ font-size: 1rem;
+
+ svg {
+ margin: 0 !important;
+ }
+ }
+
+ &.hided {
+ height: 0;
+ }
+
+ span {
+ width: 100%;
+ }
+
+ .ant-upload {
+ width: 100%;
+ }
+ }
+
.textInput {
- display : flex;
- width : 100%;
- transition : height 150ms ease-in-out;
+ display: flex;
+ width: 100%;
+ transition: height 150ms ease-in-out;
background-color: var(--background-color-accent);
svg {
@@ -17,14 +201,14 @@
}
.avatar {
- width : fit-content;
+ width: fit-content;
height: 45px;
display: flex;
img {
- width : 45px;
- height : 45px;
+ width: 45px;
+ height: 45px;
border-radius: 12px;
}
}
@@ -35,7 +219,7 @@
.textArea {
border-radius: 8px !important;
- transition : all 150ms ease-in-out !important;
+ transition: all 150ms ease-in-out !important;
&.active {
background-color: var(--background-color-primary);
@@ -43,27 +227,27 @@
}
.ant-btn-primary {
- z-index : 10;
- position : relative;
- border-radius : 0 10px 10px 0;
- height : 100%;
+ z-index: 10;
+ position: relative;
+ border-radius: 0 10px 10px 0;
+ height: 100%;
vertical-align: bottom;
- border : none;
- box-shadow : none;
+ border: none;
+ box-shadow: none;
}
.ant-input {
background-color: var(--background-color-accent);
- z-index : 10;
- position : relative;
- border-color : transparent !important;
- box-shadow : none;
+ z-index: 10;
+ position: relative;
+ border-color: transparent !important;
+ box-shadow: none;
border-radius: 3px 0 0;
- height : 100%;
- padding : 5px 10px;
- transition : height 150ms linear;
- width : 100%;
+ height: 100%;
+ padding: 5px 10px;
+ transition: height 150ms linear;
+ width: 100%;
}
.ant-btn-primary[disabled] {