├── .DS_Store ├── client ├── .DS_Store ├── .next │ ├── react-loadable-manifest.json │ ├── server │ │ ├── middleware-manifest.json │ │ └── webpack-runtime.js │ └── static │ │ └── development │ │ ├── _middlewareManifest.js │ │ └── _ssgManifest.js ├── README.md ├── assets │ ├── check.png │ ├── cp.png │ ├── error.png │ └── metamask.png ├── components │ ├── Post.tsx │ ├── Sidebar.tsx │ ├── SidebarOption.tsx │ ├── Widgets.tsx │ ├── home │ │ ├── Feed.tsx │ │ └── TweetBox.tsx │ └── profile │ │ ├── ProfileHeader.tsx │ │ ├── ProfileTweets.tsx │ │ └── mintingModal │ │ ├── FinishedState.tsx │ │ ├── InitialState.tsx │ │ ├── LoadingState.tsx │ │ └── ProfileImageMinter.tsx ├── context │ └── TwitterContext.js ├── lib │ ├── ProfileImageNfts.json │ ├── client.js │ ├── constants.js │ ├── hexStyles.css │ ├── pinata.js │ └── static.js ├── next-env.d.ts ├── next.config.js ├── package.json ├── pages │ ├── _app.tsx │ ├── api │ │ └── hello.ts │ ├── index.tsx │ └── profile.tsx ├── postcss.config.js ├── public │ ├── favicon.ico │ └── vercel.svg ├── styles │ ├── Home.module.css │ └── globals.css ├── tailwind.config.js ├── tsconfig.json └── yarn.lock ├── smart_contract ├── .DS_Store ├── .gitignore ├── README.md ├── contracts │ └── MintProfileImage.sol ├── hardhat.config.js ├── package-lock.json ├── package.json ├── scripts │ └── deploy.js ├── test │ └── sample-test.js └── yarn.lock └── studio ├── .DS_Store ├── .eslintrc ├── README.md ├── config ├── .checksums └── @sanity │ ├── data-aspects.json │ ├── default-layout.json │ ├── default-login.json │ └── form-builder.json ├── package.json ├── plugins └── .gitkeep ├── sanity.json ├── schemas ├── schema.js ├── tweetSchema.js └── userSchema.js ├── static ├── .gitkeep └── favicon.ico ├── tsconfig.json └── yarn.lock /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CleverProgrammers/twitter-blockchain-youtube/a352cdb72195cf0d918277ebff3e1bbec7ccf878/.DS_Store -------------------------------------------------------------------------------- /client/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CleverProgrammers/twitter-blockchain-youtube/a352cdb72195cf0d918277ebff3e1bbec7ccf878/client/.DS_Store -------------------------------------------------------------------------------- /client/.next/react-loadable-manifest.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /client/.next/server/middleware-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "sortedMiddleware": [], 3 | "clientInfo": [], 4 | "middleware": {}, 5 | "version": 1 6 | } -------------------------------------------------------------------------------- /client/.next/server/webpack-runtime.js: -------------------------------------------------------------------------------- 1 | /* 2 | * ATTENTION: An "eval-source-map" devtool has been used. 3 | * This devtool is neither made for production nor for readable output files. 4 | * It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools. 5 | * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) 6 | * or disable the default devtool with "devtool: false". 7 | * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). 8 | */ 9 | /******/ (() => { // webpackBootstrap 10 | /******/ "use strict"; 11 | /******/ var __webpack_modules__ = ({}); 12 | /************************************************************************/ 13 | /******/ // The module cache 14 | /******/ var __webpack_module_cache__ = {}; 15 | /******/ 16 | /******/ // The require function 17 | /******/ function __webpack_require__(moduleId) { 18 | /******/ // Check if module is in cache 19 | /******/ var cachedModule = __webpack_module_cache__[moduleId]; 20 | /******/ if (cachedModule !== undefined) { 21 | /******/ return cachedModule.exports; 22 | /******/ } 23 | /******/ // Create a new module (and put it into the cache) 24 | /******/ var module = __webpack_module_cache__[moduleId] = { 25 | /******/ // no module.id needed 26 | /******/ // no module.loaded needed 27 | /******/ exports: {} 28 | /******/ }; 29 | /******/ 30 | /******/ // Execute the module function 31 | /******/ var threw = true; 32 | /******/ try { 33 | /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); 34 | /******/ threw = false; 35 | /******/ } finally { 36 | /******/ if(threw) delete __webpack_module_cache__[moduleId]; 37 | /******/ } 38 | /******/ 39 | /******/ // Return the exports of the module 40 | /******/ return module.exports; 41 | /******/ } 42 | /******/ 43 | /******/ // expose the modules object (__webpack_modules__) 44 | /******/ __webpack_require__.m = __webpack_modules__; 45 | /******/ 46 | /************************************************************************/ 47 | /******/ /* webpack/runtime/compat get default export */ 48 | /******/ (() => { 49 | /******/ // getDefaultExport function for compatibility with non-harmony modules 50 | /******/ __webpack_require__.n = (module) => { 51 | /******/ var getter = module && module.__esModule ? 52 | /******/ () => (module['default']) : 53 | /******/ () => (module); 54 | /******/ __webpack_require__.d(getter, { a: getter }); 55 | /******/ return getter; 56 | /******/ }; 57 | /******/ })(); 58 | /******/ 59 | /******/ /* webpack/runtime/define property getters */ 60 | /******/ (() => { 61 | /******/ // define getter functions for harmony exports 62 | /******/ __webpack_require__.d = (exports, definition) => { 63 | /******/ for(var key in definition) { 64 | /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { 65 | /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); 66 | /******/ } 67 | /******/ } 68 | /******/ }; 69 | /******/ })(); 70 | /******/ 71 | /******/ /* webpack/runtime/ensure chunk */ 72 | /******/ (() => { 73 | /******/ __webpack_require__.f = {}; 74 | /******/ // This file contains only the entry chunk. 75 | /******/ // The chunk loading function for additional chunks 76 | /******/ __webpack_require__.e = (chunkId) => { 77 | /******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => { 78 | /******/ __webpack_require__.f[key](chunkId, promises); 79 | /******/ return promises; 80 | /******/ }, [])); 81 | /******/ }; 82 | /******/ })(); 83 | /******/ 84 | /******/ /* webpack/runtime/get javascript chunk filename */ 85 | /******/ (() => { 86 | /******/ // This function allow to reference async chunks and sibling chunks for the entrypoint 87 | /******/ __webpack_require__.u = (chunkId) => { 88 | /******/ // return url for filenames based on template 89 | /******/ return undefined; 90 | /******/ }; 91 | /******/ })(); 92 | /******/ 93 | /******/ /* webpack/runtime/hasOwnProperty shorthand */ 94 | /******/ (() => { 95 | /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) 96 | /******/ })(); 97 | /******/ 98 | /******/ /* webpack/runtime/make namespace object */ 99 | /******/ (() => { 100 | /******/ // define __esModule on exports 101 | /******/ __webpack_require__.r = (exports) => { 102 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 103 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 104 | /******/ } 105 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 106 | /******/ }; 107 | /******/ })(); 108 | /******/ 109 | /******/ /* webpack/runtime/startup entrypoint */ 110 | /******/ (() => { 111 | /******/ __webpack_require__.X = (result, chunkIds, fn) => { 112 | /******/ // arguments: chunkIds, moduleId are deprecated 113 | /******/ var moduleId = chunkIds; 114 | /******/ if(!fn) chunkIds = result, fn = () => (__webpack_require__(__webpack_require__.s = moduleId)); 115 | /******/ chunkIds.map(__webpack_require__.e, __webpack_require__) 116 | /******/ var r = fn(); 117 | /******/ return r === undefined ? result : r; 118 | /******/ } 119 | /******/ })(); 120 | /******/ 121 | /******/ /* webpack/runtime/require chunk loading */ 122 | /******/ (() => { 123 | /******/ // no baseURI 124 | /******/ 125 | /******/ // object to store loaded chunks 126 | /******/ // "1" means "loaded", otherwise not loaded yet 127 | /******/ var installedChunks = { 128 | /******/ "webpack-runtime": 1 129 | /******/ }; 130 | /******/ 131 | /******/ // no on chunks loaded 132 | /******/ 133 | /******/ var installChunk = (chunk) => { 134 | /******/ var moreModules = chunk.modules, chunkIds = chunk.ids, runtime = chunk.runtime; 135 | /******/ for(var moduleId in moreModules) { 136 | /******/ if(__webpack_require__.o(moreModules, moduleId)) { 137 | /******/ __webpack_require__.m[moduleId] = moreModules[moduleId]; 138 | /******/ } 139 | /******/ } 140 | /******/ if(runtime) runtime(__webpack_require__); 141 | /******/ for(var i = 0; i < chunkIds.length; i++) 142 | /******/ installedChunks[chunkIds[i]] = 1; 143 | /******/ 144 | /******/ }; 145 | /******/ 146 | /******/ // require() chunk loading for javascript 147 | /******/ __webpack_require__.f.require = (chunkId, promises) => { 148 | /******/ // "1" is the signal for "already loaded" 149 | /******/ if(!installedChunks[chunkId]) { 150 | /******/ if("webpack-runtime" != chunkId) { 151 | /******/ installChunk(require("./" + __webpack_require__.u(chunkId))); 152 | /******/ } else installedChunks[chunkId] = 1; 153 | /******/ } 154 | /******/ }; 155 | /******/ 156 | /******/ module.exports = __webpack_require__; 157 | /******/ __webpack_require__.C = installChunk; 158 | /******/ 159 | /******/ // no HMR 160 | /******/ 161 | /******/ // no HMR manifest 162 | /******/ })(); 163 | /******/ 164 | /************************************************************************/ 165 | /******/ 166 | /******/ 167 | /******/ })() 168 | ; -------------------------------------------------------------------------------- /client/.next/static/development/_middlewareManifest.js: -------------------------------------------------------------------------------- 1 | self.__MIDDLEWARE_MANIFEST=[];self.__MIDDLEWARE_MANIFEST_CB&&self.__MIDDLEWARE_MANIFEST_CB() -------------------------------------------------------------------------------- /client/.next/static/development/_ssgManifest.js: -------------------------------------------------------------------------------- 1 | self.__SSG_MANIFEST=new Set;self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB() -------------------------------------------------------------------------------- /client/README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | ``` 12 | 13 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 14 | 15 | You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. 16 | 17 | [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`. 18 | 19 | The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. 20 | 21 | ## Learn More 22 | 23 | To learn more about Next.js, take a look at the following resources: 24 | 25 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 26 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 27 | 28 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 29 | 30 | ## Deploy on Vercel 31 | 32 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 33 | 34 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 35 | -------------------------------------------------------------------------------- /client/assets/check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CleverProgrammers/twitter-blockchain-youtube/a352cdb72195cf0d918277ebff3e1bbec7ccf878/client/assets/check.png -------------------------------------------------------------------------------- /client/assets/cp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CleverProgrammers/twitter-blockchain-youtube/a352cdb72195cf0d918277ebff3e1bbec7ccf878/client/assets/cp.png -------------------------------------------------------------------------------- /client/assets/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CleverProgrammers/twitter-blockchain-youtube/a352cdb72195cf0d918277ebff3e1bbec7ccf878/client/assets/error.png -------------------------------------------------------------------------------- /client/assets/metamask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CleverProgrammers/twitter-blockchain-youtube/a352cdb72195cf0d918277ebff3e1bbec7ccf878/client/assets/metamask.png -------------------------------------------------------------------------------- /client/components/Post.tsx: -------------------------------------------------------------------------------- 1 | import { BsFillPatchCheckFill } from 'react-icons/bs' 2 | import { FaRegComment, FaRetweet } from 'react-icons/fa' 3 | import { AiOutlineHeart } from 'react-icons/ai' 4 | import { FiShare } from 'react-icons/fi' 5 | import { format } from 'timeago.js' 6 | import { useState } from 'react' 7 | 8 | const style = { 9 | wrapper: `flex p-3 border-b border-[#38444d]`, 10 | profileImage: `rounded-full h-[40px] w-[40px] object-cover`, 11 | postMain: `flex-1 px-4`, 12 | headerDetails: `flex items-center`, 13 | name: `font-bold mr-1`, 14 | verified: `text-[0.8rem]`, 15 | handleAndTimeAgo: `text-[#8899a6] ml-1`, 16 | tweet: `my-2`, 17 | image: `rounded-3xl`, 18 | footer: `flex justify-between mr-28 mt-4 text-[#8899a6]`, 19 | footerIcon: `rounded-full text-lg p-2`, 20 | } 21 | 22 | interface PostProps { 23 | displayName: string 24 | userName: string 25 | text: string 26 | avatar: string 27 | timestamp: string 28 | isProfileImageNft: Boolean | undefined 29 | } 30 | 31 | const Post = ({ 32 | displayName, 33 | userName, 34 | text, 35 | avatar, 36 | timestamp, 37 | isProfileImageNft, 38 | }: PostProps) => { 39 | const [profileImageLink] = useState(avatar) 40 | 41 | return ( 42 |
43 |
44 | {userName} 53 |
54 |
55 |
56 | 57 | {displayName} 58 | {isProfileImageNft && ( 59 | 60 | 61 | 62 | )} 63 | 64 | @{userName} • {format(new Date(timestamp).getTime())} 65 | 66 | 67 |
{text}
68 |
69 |
70 |
73 | 74 |
75 |
78 | 79 |
80 |
83 | 84 |
85 |
88 | 89 |
90 |
91 |
92 |
93 | ) 94 | } 95 | 96 | export default Post 97 | -------------------------------------------------------------------------------- /client/components/Sidebar.tsx: -------------------------------------------------------------------------------- 1 | import { useState, useContext } from 'react' 2 | import { useRouter } from 'next/router' 3 | import { TwitterContext } from '../context/TwitterContext' 4 | import SidebarOption from './SidebarOption' 5 | import { RiHome7Line, RiHome7Fill, RiFileList2Fill } from 'react-icons/ri' 6 | import { BiHash } from 'react-icons/bi' 7 | import { FiBell, FiMoreHorizontal } from 'react-icons/fi' 8 | import { HiOutlineMail, HiMail } from 'react-icons/hi' 9 | import { FaRegListAlt, FaHashtag, FaBell } from 'react-icons/fa' 10 | import { CgMoreO } from 'react-icons/cg' 11 | import { VscTwitter } from 'react-icons/vsc' 12 | import Modal from 'react-modal' 13 | import { customStyles } from '../lib/constants' 14 | import ProfileImageMinter from './profile/mintingModal/ProfileImageMinter' 15 | import { 16 | BsBookmark, 17 | BsBookmarkFill, 18 | BsPerson, 19 | BsPersonFill, 20 | } from 'react-icons/bs' 21 | 22 | const style = { 23 | wrapper: `flex-[0.7] px-8 flex flex-col`, 24 | twitterIconContainer: `text-3xl m-4`, 25 | tweetButton: `bg-[#1d9bf0] hover:bg-[#1b8cd8] flex items-center justify-center font-bold rounded-3xl h-[50px] mt-[20px] cursor-pointer`, 26 | navContainer: `flex-1`, 27 | profileButton: `flex items-center mb-6 cursor-pointer hover:bg-[#333c45] rounded-[100px] p-2`, 28 | profileLeft: `flex item-center justify-center mr-4`, 29 | profileImage: `height-12 w-12 rounded-full`, 30 | profileRight: `flex-1 flex`, 31 | details: `flex-1`, 32 | name: `text-lg`, 33 | handle: `text-[#8899a6]`, 34 | moreContainer: `flex items-center mr-2`, 35 | } 36 | 37 | interface SidebarProps { 38 | initialSelectedIcon: string 39 | } 40 | 41 | function Sidebar({ initialSelectedIcon }: SidebarProps) { 42 | const [selected, setSelected] = useState(initialSelectedIcon) 43 | const { currentAccount, currentUser } = useContext(TwitterContext) 44 | const router = useRouter() 45 | 46 | return ( 47 |
48 |
49 | 50 |
51 |
52 | 59 | 65 | 71 | 77 | 83 | 89 | 96 | 97 |
99 | router.push(`${router.pathname}/?mint=${currentAccount}`) 100 | } 101 | className={style.tweetButton} 102 | > 103 | Mint 104 |
105 |
106 |
107 |
108 | profile 117 |
118 |
119 |
120 |
{currentUser.name}
121 |
122 | @{currentAccount.slice(0, 6)}...{currentAccount.slice(39)} 123 |
124 |
125 |
126 | 127 |
128 |
129 |
130 | 131 | router.back()} 134 | style={customStyles} 135 | > 136 | 137 | 138 |
139 | ) 140 | } 141 | 142 | export default Sidebar 143 | -------------------------------------------------------------------------------- /client/components/SidebarOption.tsx: -------------------------------------------------------------------------------- 1 | import { Dispatch, SetStateAction } from 'react' 2 | import { IconType } from 'react-icons' 3 | import { useRouter } from 'next/router' 4 | 5 | const style = { 6 | wrapper: `w-min flex items-center rounded-[100px] p-4 cursor-pointer hover:bg-[#333c45] transition-all hover:duration-200 hover:ease-in-out`, 7 | iconContainer: `text-xl mr-4`, 8 | textGeneral: `font-medium`, 9 | textActive: `font-bold`, 10 | } 11 | 12 | interface SidebarOptionProps { 13 | text: String 14 | Icon: IconType 15 | isActive?: Boolean 16 | setSelected?: Dispatch> 17 | redirect?: URL | string 18 | } 19 | 20 | function SidebarOption({ 21 | text, 22 | Icon, 23 | isActive, 24 | setSelected, 25 | redirect, 26 | }: SidebarOptionProps) { 27 | const router = useRouter() 28 | 29 | const handleClick = (buttonText = text) => { 30 | if (buttonText !== 'More' && setSelected) { 31 | setSelected(buttonText) 32 | } else return 33 | } 34 | 35 | return ( 36 |
{ 39 | handleClick(text) 40 | if (redirect) { 41 | router.push(redirect) 42 | } else return 43 | }} 44 | > 45 |
46 | 47 |
48 |
49 | {text} 50 |
51 |
52 | ) 53 | } 54 | 55 | export default SidebarOption 56 | -------------------------------------------------------------------------------- /client/components/Widgets.tsx: -------------------------------------------------------------------------------- 1 | import { news, whoToFollow } from '../lib/static' 2 | import { BiSearch } from 'react-icons/bi' 3 | 4 | const style = { 5 | wrapper: `flex-[1] p-4`, 6 | searchBar: `flex items-center bg-[#243340] p-2 rounded-3xl`, 7 | searchIcon: `text-[#8899a6] mr-2`, 8 | inputBox: `bg-transparent outline-none`, 9 | section: `bg-[#192734] my-6 rounded-xl overflow-hidden`, 10 | title: `p-2 font-bold text-lg`, 11 | showMore: `p-2 text-[#1d9bf0] text-sm cursor-pointer hover:bg-[#22303c]`, 12 | item: `flex items-center p-3 my-2 hover:bg-[#22303c] cursor-pointer`, 13 | newsItemLeft: `flex-1`, 14 | newsItemCategory: `text-[#8899a6] text-xs font-semibold`, 15 | newsItemTitle: `text-sm font-bold`, 16 | newsItemRight: `w-1/5 ml-3`, 17 | newsItemImage: `rounded-xl h-14 w-14 object-cover`, 18 | followAvatarContainer: `w-1/6`, 19 | followAvatar: `rounded-full h-[40px] w-[40px]`, 20 | profileDetails: `flex-1`, 21 | name: `font-bold`, 22 | handle: `text-[#8899a6]`, 23 | followButton: `bg-white text-black px-3 py-1 rounded-full text-xs font-bold`, 24 | } 25 | 26 | function Widgets() { 27 | return ( 28 |
29 |
30 | 31 | 36 |
37 |
38 |
What's happening
39 | {news.map((item, index) => ( 40 |
41 |
42 |
{item.category}
43 |
{item.title}
44 |
45 |
46 | {item.category} 51 |
52 |
53 | ))} 54 |
Show more
55 |
56 |
57 |
Who to follow
58 | {whoToFollow.map((item, index) => ( 59 |
60 |
61 | {item.handle} 66 |
67 |
68 |
{item.name}
69 |
{item.handle}
70 |
71 |
Follow
72 |
73 | ))} 74 |
Show more
75 |
76 |
77 | ) 78 | } 79 | 80 | export default Widgets 81 | -------------------------------------------------------------------------------- /client/components/home/Feed.tsx: -------------------------------------------------------------------------------- 1 | import { useContext, useEffect } from 'react' 2 | import { TwitterContext } from '../../context/TwitterContext' 3 | import TweetBox from './TweetBox' 4 | import Post from '../Post' 5 | import { BsStars } from 'react-icons/bs' 6 | 7 | const style = { 8 | wrapper: `flex-[2] border-r border-l border-[#38444d] overflow-y-scroll`, 9 | header: `sticky top-0 bg-[#15202b] z-10 p-4 flex justify-between items-center`, 10 | headerTitle: `text-xl font-bold`, 11 | } 12 | 13 | interface Tweet { 14 | author: TweetAuthor 15 | tweet: string 16 | timestamp: string 17 | } 18 | 19 | interface TweetAuthor { 20 | name: string 21 | walletAddress: string 22 | profileImage: string 23 | isProfileImageNft: boolean 24 | } 25 | 26 | function Feed() { 27 | const { tweets } = useContext(TwitterContext) 28 | 29 | return ( 30 |
31 |
32 |
Home
33 | 34 |
35 | 36 | {tweets.map((tweet: Tweet, index: number) => ( 37 | 56 | ))} 57 |
58 | ) 59 | } 60 | 61 | export default Feed 62 | -------------------------------------------------------------------------------- /client/components/home/TweetBox.tsx: -------------------------------------------------------------------------------- 1 | import { useState, useContext } from 'react' 2 | import { TwitterContext } from '../../context/TwitterContext' 3 | import { BsCardImage, BsEmojiSmile } from 'react-icons/bs' 4 | import { RiFileGifLine, RiBarChartHorizontalFill } from 'react-icons/ri' 5 | import { IoMdCalendar } from 'react-icons/io' 6 | import { MdOutlineLocationOn } from 'react-icons/md' 7 | import { client } from '../../lib/client' 8 | 9 | const style = { 10 | wrapper: `px-4 flex flex-row border-b border-[#38444d] pb-4`, 11 | tweetBoxLeft: `mr-4`, 12 | tweetBoxRight: `flex-1`, 13 | profileImage: `height-12 w-12 rounded-full`, 14 | inputField: `w-full h-full outline-none bg-transparent text-lg`, 15 | formLowerContainer: `flex`, 16 | iconsContainer: `text-[#1d9bf0] flex flex-1 items-center`, 17 | icon: `mr-2`, 18 | submitGeneral: `px-6 py-2 rounded-3xl font-bold`, 19 | inactiveSubmit: `bg-[#196195] text-[#95999e]`, 20 | activeSubmit: `bg-[#1d9bf0] text-white`, 21 | } 22 | 23 | function TweetBox() { 24 | const [tweetMessage, setTweetMessage] = useState('') 25 | const { currentAccount, fetchTweets, currentUser } = 26 | useContext(TwitterContext) 27 | 28 | const submitTweet = async (event: any) => { 29 | event.preventDefault() 30 | 31 | if (!tweetMessage) return 32 | const tweetId = `${currentAccount}_${Date.now()}` 33 | 34 | const tweetDoc = { 35 | _type: 'tweets', 36 | _id: tweetId, 37 | tweet: tweetMessage, 38 | timestamp: new Date(Date.now()).toISOString(), 39 | author: { 40 | _key: tweetId, 41 | _ref: currentAccount, 42 | _type: 'reference', 43 | }, 44 | } 45 | 46 | await client.createIfNotExists(tweetDoc) 47 | 48 | await client 49 | .patch(currentAccount) 50 | .setIfMissing({ tweets: [] }) 51 | .insert('after', 'tweets[-1]', [ 52 | { 53 | _key: tweetId, 54 | _ref: tweetId, 55 | _type: 'reference', 56 | }, 57 | ]) 58 | .commit() 59 | 60 | await fetchTweets() 61 | setTweetMessage('') 62 | } 63 | 64 | return ( 65 |
66 |
67 | 75 |
76 |
77 |
78 |