Last active
February 10, 2022 16:06
-
-
Save lorisleiva/94c00757a57f4a60e0577663de2ab6d0 to your computer and use it in GitHub Desktop.
TweetCard and TweetFormUpdate for Episode 12 of the Solana series.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script setup> | |
import { ref, toRefs, computed } from 'vue' | |
import { useWorkspace } from '@/composables' | |
import TweetFormUpdate from './TweetFormUpdate' | |
const props = defineProps({ | |
tweet: Object, | |
}) | |
const { tweet } = toRefs(props) | |
const { wallet } = useWorkspace() | |
const isMyTweet = computed(() => wallet.value && wallet.value.publicKey.toBase58() === tweet.value.author.toBase58()) | |
const authorRoute = computed(() => { | |
if (isMyTweet.value) { | |
return { name: 'Profile' } | |
} else { | |
return { name: 'Users', params: { author: tweet.value.author.toBase58() } } | |
} | |
}) | |
const isEditing = ref(false) | |
</script> | |
<template> | |
<tweet-form-update v-if="isEditing" :tweet="tweet" @close="isEditing = false"></tweet-form-update> | |
<div class="px-8 py-4" v-else> | |
<div class="flex justify-between"> | |
<div class="py-1"> | |
<h3 class="inline font-semibold" :title="tweet.author"> | |
<router-link :to="authorRoute" class="hover:underline"> | |
{{ tweet.author_display }} | |
</router-link> | |
</h3> | |
<span class="text-gray-500"> • </span> | |
<time class="text-gray-500 text-sm" :title="tweet.created_at"> | |
<router-link :to="{ name: 'Tweet', params: { tweet: tweet.publicKey.toBase58() } }" class="hover:underline"> | |
{{ tweet.created_ago }} | |
</router-link> | |
</time> | |
</div> | |
<div class="flex" v-if="isMyTweet"> | |
<button @click="isEditing = true" class="flex px-2 rounded-full text-gray-500 hover:text-pink-500 hover:bg-gray-100" title="Update tweet"> | |
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 m-auto" viewBox="0 0 20 20" fill="currentColor"> | |
<path d="M17.414 2.586a2 2 0 00-2.828 0L7 10.172V13h2.828l7.586-7.586a2 2 0 000-2.828z" /> | |
<path fill-rule="evenodd" d="M2 6a2 2 0 012-2h4a1 1 0 010 2H4v10h10v-4a1 1 0 112 0v4a2 2 0 01-2 2H4a2 2 0 01-2-2V6z" clip-rule="evenodd" /> | |
</svg> | |
</button> | |
</div> | |
</div> | |
<p class="whitespace-pre-wrap break-all" v-text="tweet.content"></p> | |
<router-link v-if="tweet.topic" :to="{ name: 'Topics', params: { topic: tweet.topic } }" class="inline-block mt-2 text-pink-500 hover:underline"> | |
#{{ tweet.topic }} | |
</router-link> | |
</div> | |
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script setup> | |
import { computed, ref, toRefs } from 'vue' | |
import { useAutoresizeTextarea, useCountCharacterLimit, useSlug } from '@/composables' | |
import { updateTweet } from '@/api' | |
import { useWallet } from 'solana-wallets-vue' | |
// Props. | |
const props = defineProps({ | |
tweet: Object, | |
}) | |
const { tweet } = toRefs(props) | |
// Form data. | |
const content = ref(tweet.value.content) | |
const topic = ref(tweet.value.topic) | |
const slugTopic = useSlug(topic) | |
// Auto-resize the content's textarea. | |
const textarea = ref() | |
useAutoresizeTextarea(textarea) | |
// Character limit / count-down. | |
const characterLimit = useCountCharacterLimit(content, 280) | |
const characterLimitColour = computed(() => { | |
if (characterLimit.value < 0) return 'text-red-500' | |
if (characterLimit.value <= 10) return 'text-yellow-500' | |
return 'text-gray-400' | |
}) | |
// Permissions. | |
const { connected } = useWallet() | |
const canTweet = computed(() => content.value && characterLimit.value > 0) | |
// Actions. | |
const emit = defineEmits(['close']) | |
const update = async () => { | |
if (! canTweet.value) return | |
await updateTweet(tweet.value, slugTopic.value, content.value) | |
emit('close') | |
} | |
</script> | |
<template> | |
<div v-if="connected"> | |
<div class="px-8 py-4 border-l-4 border-pink-500"> | |
<div class="py-1"> | |
<h3 class="inline font-semibold" :title="tweet.author"> | |
<router-link :to="{ name: 'Profile' }" class="hover:underline"> | |
{{ tweet.author_display }} | |
</router-link> | |
</h3> | |
<span class="text-gray-500"> • </span> | |
<time class="text-gray-500 text-sm" :title="tweet.created_at"> | |
<router-link :to="{ name: 'Tweet', params: { tweet: tweet.publicKey.toBase58() } }" class="hover:underline"> | |
{{ tweet.created_ago }} | |
</router-link> | |
</time> | |
</div> | |
<!-- Content field. --> | |
<textarea | |
ref="textarea" | |
rows="1" | |
class="text-xl w-full focus:outline-none resize-none mb-3" | |
placeholder="What's happening?" | |
v-model="content" | |
></textarea> | |
<div class="flex flex-wrap items-center justify-between -m-2"> | |
<!-- Topic field. --> | |
<div class="relative m-2 mr-4"> | |
<input | |
type="text" | |
placeholder="topic" | |
class="text-pink-500 rounded-full pl-10 pr-4 py-2 bg-gray-100" | |
:value="slugTopic" | |
@input="topic = $event.target.value" | |
> | |
<div class="absolute left-0 inset-y-0 flex pl-3 pr-2"> | |
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 m-auto" :class="slugTopic ? 'text-pink-500' : 'text-gray-400'" viewBox="0 0 20 20" fill="currentColor"> | |
<path fill-rule="evenodd" d="M9.243 3.03a1 1 0 01.727 1.213L9.53 6h2.94l.56-2.243a1 1 0 111.94.486L14.53 6H17a1 1 0 110 2h-2.97l-1 4H15a1 1 0 110 2h-2.47l-.56 2.242a1 1 0 11-1.94-.485L10.47 14H7.53l-.56 2.242a1 1 0 11-1.94-.485L5.47 14H3a1 1 0 110-2h2.97l1-4H5a1 1 0 110-2h2.47l.56-2.243a1 1 0 011.213-.727zM9.03 8l-1 4h2.938l1-4H9.031z" clip-rule="evenodd" /> | |
</svg> | |
</div> | |
</div> | |
<div class="flex items-center space-x-4 m-2 ml-auto"> | |
<!-- Character limit. --> | |
<div :class="characterLimitColour"> | |
{{ characterLimit }} left | |
</div> | |
<!-- Close button. --> | |
<button | |
class="text-gray-500 px-4 py-2 rounded-full border bg-white hover:bg-gray-50" | |
@click="emit('close')" | |
> | |
Cancel | |
</button> | |
<!-- Tweet button. --> | |
<button | |
class="text-white px-4 py-2 rounded-full font-semibold" :disabled="! canTweet" | |
:class="canTweet ? 'bg-pink-500' : 'bg-pink-300 cursor-not-allowed'" | |
@click="update" | |
> | |
Update | |
</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div v-else class="px-8 py-4 bg-gray-50 text-gray-500 text-center border-b"> | |
Connect your wallet to start tweeting... | |
</div> | |
</template> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment