mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-09-07 19:55:46 -05:00
vouching frontend
This commit is contained in:
@@ -38,7 +38,7 @@ const getAction = (success, onClick) => {
|
||||
}
|
||||
|
||||
const PlusPage = () => {
|
||||
const [showSuggestionForm, setShowSuggestionForm] = useState(false)
|
||||
const [showSuggestionForm, setShowSuggestionForm] = useState(true)
|
||||
const plusOneRef = useRef(null)
|
||||
const [plusOneCopySuccess, setPlusOneCopySuccess] = useState(false)
|
||||
const plusTwoRef = useRef(null)
|
||||
|
||||
@@ -7,15 +7,20 @@ import UserSearch from "../common/UserSearch"
|
||||
import TextAreaWithLimit from "../common/TextAreaWithLimit"
|
||||
import { addSuggestion } from "../../graphql/mutations/addSuggestion"
|
||||
import { suggestions } from "../../graphql/queries/suggestions"
|
||||
import { vouches } from "../../graphql/queries/vouches"
|
||||
import { addVouch } from "../../graphql/mutations/addVouch"
|
||||
|
||||
const SuggestionForm = ({
|
||||
plusServer,
|
||||
hideForm,
|
||||
handleSuccess,
|
||||
handleError,
|
||||
canSuggest,
|
||||
canVouch,
|
||||
canVouchFor,
|
||||
}) => {
|
||||
const [selectedUser, setSelectedUser] = useState(null)
|
||||
const [form, setForm] = useState({})
|
||||
const [form, setForm] = useState({ type: !canSuggest ? "VOUCH" : "SUGGEST" })
|
||||
|
||||
const [addSuggestionMutation] = useMutation(addSuggestion, {
|
||||
onError: handleError,
|
||||
@@ -27,19 +32,61 @@ const SuggestionForm = ({
|
||||
],
|
||||
})
|
||||
|
||||
const [addVouchMutation] = useMutation(addVouch, {
|
||||
onError: handleError,
|
||||
onCompleted: () =>
|
||||
handleSuccess(
|
||||
"Vouch successfully added. Let them know and send them an invite link to the server!"
|
||||
),
|
||||
refetchQueries: [
|
||||
{
|
||||
query: vouches,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const handleSubmit = async event => {
|
||||
event.preventDefault()
|
||||
await addSuggestionMutation({
|
||||
variables: { ...form, discord_id: selectedUser.id },
|
||||
})
|
||||
if (form.type === "SUGGEST") {
|
||||
await addSuggestionMutation({
|
||||
variables: { ...form, discord_id: selectedUser.id },
|
||||
})
|
||||
} else {
|
||||
await addVouchMutation({
|
||||
variables: { ...form, discord_id: selectedUser.id },
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
console.log("CanVouchFor", canVouchFor)
|
||||
|
||||
return (
|
||||
<>
|
||||
{selectedUser ? (
|
||||
<Form onSubmit={handleSubmit}>
|
||||
<Form.Field required>
|
||||
<Form.Field>
|
||||
<Radio
|
||||
label="Suggest"
|
||||
disabled={!canSuggest}
|
||||
value="SUGGEST"
|
||||
checked={form.type === "SUGGEST"}
|
||||
onChange={() => setForm({ type: "SUGGEST" })}
|
||||
/>
|
||||
</Form.Field>
|
||||
<Form.Field>
|
||||
<Radio
|
||||
label="Vouch"
|
||||
value="VOUCH"
|
||||
disabled={!canVouch}
|
||||
checked={form.type === "VOUCH"}
|
||||
onChange={() => setForm({ type: "VOUCH" })}
|
||||
/>
|
||||
</Form.Field>
|
||||
</Form.Field>
|
||||
<Form.Field>
|
||||
<h3>Suggesting</h3>
|
||||
{form.type === "SUGGEST" && <h3>Suggesting</h3>}
|
||||
{form.type === "VOUCH" && <h3>Vouching</h3>}
|
||||
</Form.Field>
|
||||
<Form.Field>
|
||||
<div>
|
||||
@@ -53,11 +100,7 @@ const SuggestionForm = ({
|
||||
</Link>
|
||||
{selectedUser.description && (
|
||||
<div style={{ marginTop: "0.5em" }}>
|
||||
<Icon
|
||||
name="twitter"
|
||||
size="large"
|
||||
style={{ color: "#1da1f2" }}
|
||||
/>
|
||||
<Icon name="twitter" style={{ color: "#1da1f2" }} />
|
||||
<a
|
||||
href={`https://twitter.com/${selectedUser.description}`}
|
||||
target="_blank"
|
||||
@@ -74,7 +117,10 @@ const SuggestionForm = ({
|
||||
<Form.Field>
|
||||
<Radio
|
||||
label="+1"
|
||||
disabled={plusServer !== "ONE"}
|
||||
disabled={
|
||||
(form.type === "SUGGEST" && plusServer !== "ONE") ||
|
||||
(form.type === "VOUCH" && canVouchFor !== "ONE")
|
||||
}
|
||||
value="ONE"
|
||||
checked={form.server === "ONE"}
|
||||
onChange={() => setForm({ ...form, server: "ONE" })}
|
||||
@@ -91,6 +137,11 @@ const SuggestionForm = ({
|
||||
</Form.Field>
|
||||
<Form.Field required>
|
||||
<label>Region</label>
|
||||
<Form.Field>
|
||||
If the player doesn't live in either Europe or The Americas you
|
||||
can choose the region based on who they are playing more often
|
||||
with.
|
||||
</Form.Field>
|
||||
<Form.Field>
|
||||
<Radio
|
||||
label="Europe"
|
||||
@@ -107,32 +158,44 @@ const SuggestionForm = ({
|
||||
onChange={() => setForm({ ...form, region: "NA" })}
|
||||
/>
|
||||
</Form.Field>
|
||||
<Form.Field>
|
||||
If the player suggested doesn't live in either Europe or The
|
||||
Americas you can choose the region based on who they are playing
|
||||
more often with.
|
||||
</Form.Field>
|
||||
{form.type === "SUGGEST" && (
|
||||
<Form.Field required>
|
||||
<label>Description</label>
|
||||
<Form.Field>
|
||||
<TextAreaWithLimit
|
||||
value={form.description}
|
||||
setValue={value => setForm({ ...form, description: value })}
|
||||
limit={1000}
|
||||
/>
|
||||
</Form.Field>
|
||||
</Form.Field>
|
||||
</Form.Field>
|
||||
<Form.Field required>
|
||||
<label>Description</label>
|
||||
)}
|
||||
{form.type === "SUGGEST" ? (
|
||||
<Form.Field>
|
||||
<TextAreaWithLimit
|
||||
value={form.description}
|
||||
setValue={value => setForm({ ...form, description: value })}
|
||||
limit={1000}
|
||||
/>
|
||||
<b>
|
||||
You can't edit or delete a suggestion after you have submitted
|
||||
it. One suggestion per month.
|
||||
</b>
|
||||
</Form.Field>
|
||||
</Form.Field>
|
||||
<Form.Field>
|
||||
<b>
|
||||
You can't edit or delete a suggestion after you have submitted it.
|
||||
One suggestion per month.
|
||||
</b>
|
||||
</Form.Field>
|
||||
) : (
|
||||
<Form.Field>
|
||||
<b>
|
||||
You can't change or delete a vouch after you have submitted it.
|
||||
One vouch per player active at any given time. If your vouch
|
||||
gets kicked in their first voting you may not vouch for the next
|
||||
6 months.
|
||||
</b>
|
||||
</Form.Field>
|
||||
)}
|
||||
<Form.Field>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={!form.server || !form.region || !form.description}
|
||||
disabled={
|
||||
(form.type === "SUGGEST" &&
|
||||
(!form.server || !form.region || !form.description)) ||
|
||||
(form.type === "VOUCH" && (!form.server || !form.region))
|
||||
}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
|
||||
@@ -6,6 +6,8 @@ import SuggestionForm from "./SuggestionForm"
|
||||
import { suggestions } from "../../graphql/queries/suggestions"
|
||||
import Loading from "../common/Loading"
|
||||
import Error from "../common/Error"
|
||||
import { vouches } from "../../graphql/queries/vouches"
|
||||
import UserAvatar from "../common/UserAvatar"
|
||||
|
||||
const SuggestionList = ({ suggestionsArray }) => {
|
||||
if (suggestionsArray.length === 0) return null
|
||||
@@ -81,21 +83,39 @@ const Suggestions = ({
|
||||
handleError,
|
||||
}) => {
|
||||
const { data, error, loading } = useQuery(suggestions)
|
||||
const {
|
||||
data: vouchesData,
|
||||
error: vouchesError,
|
||||
loading: vouchesLoading,
|
||||
} = useQuery(vouches)
|
||||
|
||||
if (loading) return <Loading minHeight="250px" />
|
||||
if (loading || vouchesLoading) return <Loading minHeight="250px" />
|
||||
if (error) return <Error errorMessage={error.message} />
|
||||
if (vouchesError) return <Error errorMessage={vouchesError.message} />
|
||||
|
||||
const ownSuggestion = data.suggestions.find(
|
||||
suggestion =>
|
||||
suggestion.suggester_discord_user.discord_id === user.discord_id
|
||||
)
|
||||
|
||||
const canSuggest = !ownSuggestion
|
||||
|
||||
const canVouch = Boolean(
|
||||
user.plus.can_vouch && !user.plus.can_vouch_again_after
|
||||
)
|
||||
|
||||
const getButtonText = () => {
|
||||
if (canSuggest && canVouch) return "Suggest or vouch a player"
|
||||
else if (canSuggest) return "Suggest a player"
|
||||
else if (canVouch) return "Vouch a player"
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{!showSuggestionForm && !ownSuggestion && (
|
||||
{!showSuggestionForm && (canSuggest || canVouch) && (
|
||||
<div style={{ marginTop: "2em" }}>
|
||||
<Button onClick={() => setShowSuggestionForm(true)}>
|
||||
Suggest a player
|
||||
{getButtonText()}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
@@ -105,8 +125,40 @@ const Suggestions = ({
|
||||
hideForm={() => setShowSuggestionForm(false)}
|
||||
handleSuccess={handleSuccess}
|
||||
handleError={handleError}
|
||||
canSuggest={canSuggest}
|
||||
canVouch={canVouch}
|
||||
canVouchFor={user.plus.can_vouch}
|
||||
/>
|
||||
)}
|
||||
{vouchesData.vouches.length > 0 && (
|
||||
<>
|
||||
<h2>Vouched</h2>
|
||||
<List>
|
||||
{vouchesData.vouches.map(vouch => {
|
||||
return (
|
||||
<List.Item
|
||||
key={vouch.username}
|
||||
style={{
|
||||
marginTop: "0.5em",
|
||||
}}
|
||||
>
|
||||
<UserAvatar twitterName={vouch.twitter_name} paddingIfNull />
|
||||
<List.Content>
|
||||
<List.Header as="a" href={`/u/${vouch.discord_id}`}>
|
||||
{vouch.username}#{vouch.discriminator}{" "}
|
||||
</List.Header>
|
||||
<List.Description>
|
||||
Vouched by {vouch.plus.voucher_user.username}#
|
||||
{vouch.plus.voucher_user.discriminator} to{" "}
|
||||
{vouch.plus.vouch_status === "ONE" ? "+1" : "+2"}
|
||||
</List.Description>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
)
|
||||
})}
|
||||
</List>
|
||||
</>
|
||||
)}
|
||||
<SuggestionList suggestionsArray={data.suggestions} />
|
||||
</>
|
||||
)
|
||||
|
||||
7
frontend-react/src/graphql/mutations/addVouch.js
Normal file
7
frontend-react/src/graphql/mutations/addVouch.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import { gql } from "apollo-boost"
|
||||
|
||||
export const addVouch = gql`
|
||||
mutation addVouch($discord_id: String!, $server: String!, $region: String!) {
|
||||
addVouch(discord_id: $discord_id, server: $server, region: $region)
|
||||
}
|
||||
`
|
||||
@@ -12,6 +12,8 @@ export const userLean = gql`
|
||||
membership_status
|
||||
plus_region
|
||||
vouch_status
|
||||
can_vouch
|
||||
can_vouch_again_after
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
20
frontend-react/src/graphql/queries/vouches.js
Normal file
20
frontend-react/src/graphql/queries/vouches.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import { gql } from "apollo-boost"
|
||||
|
||||
export const vouches = gql`
|
||||
{
|
||||
vouches {
|
||||
username
|
||||
discriminator
|
||||
twitter_name
|
||||
discord_id
|
||||
plus {
|
||||
voucher_user {
|
||||
username
|
||||
discriminator
|
||||
discord_id
|
||||
}
|
||||
vouch_status
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
@@ -15,6 +15,7 @@ const typeDef = gql`
|
||||
plusInfo: PlusGeneralInfo
|
||||
hasAccess(discord_id: String!, server: String!): Boolean!
|
||||
suggestions: [Suggested!]!
|
||||
vouches: [User!]
|
||||
usersForVoting: UsersForVoting!
|
||||
summaries: [Summary!]
|
||||
}
|
||||
@@ -70,6 +71,7 @@ const typeDef = gql`
|
||||
plus_region: PlusRegion
|
||||
can_vouch: PlusServer
|
||||
voucher_discord_id: String
|
||||
voucher_user: User
|
||||
can_vouch_again_after: String
|
||||
}
|
||||
|
||||
@@ -286,6 +288,16 @@ const resolvers = {
|
||||
})
|
||||
})
|
||||
},
|
||||
vouches: (root, args, { user }) => {
|
||||
if (!user || !user.plus) return null
|
||||
const searchCriteria =
|
||||
user.plus.membership_status === "ONE"
|
||||
? { "plus.vouch_status": { $ne: null } }
|
||||
: { "plus.vouch_status": "TWO" }
|
||||
return User.find(searchCriteria)
|
||||
.sort({ "plus.vouch_status": "asc" })
|
||||
.populate("plus.voucher_user")
|
||||
},
|
||||
summaries: (root, args, ctx) => {
|
||||
if (!ctx.user || !ctx.user.plus || !ctx.user.plus.membership_status)
|
||||
return null
|
||||
|
||||
@@ -24,4 +24,11 @@ const userSchema = new mongoose.Schema({
|
||||
},
|
||||
})
|
||||
|
||||
userSchema.virtual("plus.voucher_user", {
|
||||
ref: "User",
|
||||
localField: "plus.voucher_discord_id",
|
||||
foreignField: "discord_id",
|
||||
justOne: true,
|
||||
})
|
||||
|
||||
module.exports = mongoose.model("User", userSchema)
|
||||
|
||||
Reference in New Issue
Block a user