vouching frontend

This commit is contained in:
Sendou
2020-01-08 14:49:51 +02:00
parent 9b2ab05c59
commit 60f63a1df3
8 changed files with 198 additions and 35 deletions

View File

@@ -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)

View File

@@ -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>

View File

@@ -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} />
</>
)

View 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)
}
`

View File

@@ -12,6 +12,8 @@ export const userLean = gql`
membership_status
plus_region
vouch_status
can_vouch
can_vouch_again_after
}
}
}

View 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
}
}
}
`

View File

@@ -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

View File

@@ -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)