DEV Community

Cover image for #30DaysofAppwrite : Create User Profiles
Torsten Dittmann for Appwrite

Posted on • Updated on

#30DaysofAppwrite : Create User Profiles

Intro

#30DaysOfAppwrite is a month-long event focused on giving developers a walk-through of all of Appwrite's features, starting from the basics to more advanced features like Cloud Functions! Alongside we will also be building a fully-featured Medium clone to demonstrate how these
concepts can be applied when building a real-world app. We also have some exciting prizes for developers who follow along with us!

Create User Profiles

Welcome back to another session on the Appwrite Database 👋 . We hope you have gone through the Day 16 article. We are building upon the knowledge gained on Day 16 and plan to work on the database for our demo application, so make sure you've caught up with our progress.

Create A Profile

We will use the Profile Collection to give the users on our app a profile with a display name so that we can display the author's information in each post.

For this, we need to add two methods to our appwrite.js file: one to fetch a profile and another to create one. Let's restrict the user from creating more than one profile per account. First, we need to check if they have already created a profile on their account. We are going to add a fetchUser() function that will list all documents in the Profiles Collection, with the user field equal to the ID of our account and limiting the number of documents to 1.

import { Query } from 'appwrite';

export const api = {
    //...
    fetchUser: async id => {
        let res = await sdk.database.listDocuments(
            profilesCollection,
            [Query.equal('user', id)],
            1
        );
        if (res.total > 0 && res.documents.length > 0) return res.documents[0];
        else throw Error("Not found");
    }
};
Enter fullscreen mode Exit fullscreen mode

Notice the query Query.equal('user', id) passed into listDocuments(), which will filter the requested documents by the user field, which matches the provided id.

As you might have noticed, we are using an unknown variable called profilesCollection in the listDocuments call. For this to work, we need to create two variables that represent the unique ID of our collections. Simply prepend the following before the const api:

const profilesCollection = "[INSERT YOUR ID HERE]";
const postsCollection = "[INSERT YOUR ID HERE]";
const bucketId = "[INSERT YOUR ID HERE]";
Enter fullscreen mode Exit fullscreen mode

Make sure you use the IDs found in your dashboard and replace the one found in Profile with profilesCollection and the one found in the Post Collection with postsCollection.

Now that we can check if a profile exists, the user needs to be able to create their profile if it doesn't exist. For this, we are going to introduce the createUser method to appwrite.js:

export const api = {
    //...
    createUser: async (id, name) => {
        return sdk.database.createDocument(
            profilesCollection,
            'unique()',
            {
                user: id,
                name: name,
            },
            ["role:all"],
            [`user:${id}`]
        );
    },
}
Enter fullscreen mode Exit fullscreen mode

This will create a document in the Profile collection when called. As you can see, the second argument is an object that adheres to the collection rules we created on Day 16.

After this, the read and write permissions are passed. Since we want everyone to be able to view this profile, but only the user themselves to edit it - the read permissions will be * and the write permissions will be the user itself.

Now that we have all the Appwrite communication logic ready, we now need to add Routes and Components for it. For this, we create the src/routes/Profile.svelte file, which will display profiles.

// src/routes/Profile.svelte
<script>
    import Loading from "../lib/Loading.svelte";

    import { api } from "../appwrite";
    import { state } from "../store";

    export let params = {};

    const fetchUser = api.fetchUser(params.id);
</script>

<section>
    {#await fetchUser}
        <Loading />
    {:then author}
        <section class="author">
            <h3>{author.name}</h3>
        </section>
        {#if $state.user.$id == params.id}
            <h1>My Posts</h1>
            <section class="my-post">
                TBD
            </section>
        {:else}
            <h1>Latest Posts</h1>
            <section class="latest">
                TBD
            </section>
        {/if}
    {:catch error}
        {error}
        <p>
            Public profile not found
            <a href="#/profile/create">Create Public Profile</a>
        </p>
    {/await}
</section>

<style>
    section.author {
        display: flex;
        align-items: center;
        gap: 1rem;
    }
    section.latest {
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
        justify-content: center;
        align-items: auto;
        align-content: start;
        gap: 1rem;
    }
    section.my-post {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: auto;
        align-content: start;
        gap: 0.5rem;
    }
    a {
        border: none;
        padding: 10px;
        color: white;
        font-weight: bold;
    }
    a:hover {
        text-decoration: underline;
    }
</style>
Enter fullscreen mode Exit fullscreen mode

When we catch the error, we prompt the user to create their profile and navigate them to #/profile/create. Since this route is not created yet, create a new file called src/routes/CreateProfile.svelte. As done before, we are going to introduce that component to the router in src/App.svelte:

//src/App.svelte

import CreateProfile from "./routes/CreateProfile.svelte";  
// First import the svelte component

const routes = {
        //...
    "/profile/create": CreateProfile, // Add this component
    //...
  };
Enter fullscreen mode Exit fullscreen mode

Now we need to take care of the CreateProfile.svelte file:

<script>
    import { state } from "../store";
    import { api } from "../appwrite";
    import { replace } from "svelte-spa-router";
    let name = $state.user.name;
    const submit = async () => {
        try {
            await api.createUser($state.user.$id, name);
            replace(`/profile/${$state.user.$id}`);
        } catch (error) {
            console.log(error.message);
        }
    };
</script>

<form on:submit|preventDefault={submit}>
    {#if $state.user}
        <label for="name">Display Name</label>
        <input type="text" name="name" bind:value={name} />
        <button class="button" type="submit">Create</button>
    {/if}
</form>

<style>
    form {
        margin: auto;
        width: 500;
        display: flex;
        flex-direction: column;
    }
</style>

Enter fullscreen mode Exit fullscreen mode

This is a simple form where the user can input their Profile name and create it!

We have now added user profiles to our application using the Database and Collections we created before. On Day 18, we will add posts to the main page and let the users create posts! So stay tuned.

Credits

We hope you liked this write-up. You can follow #30DaysOfAppwrite on Social Media to keep up with all of our posts. The complete event timeline can be found here

Feel free to reach out to us on Discord if you would like to learn more about Appwrite, Aliens or Unicorns 🦄. Stay tuned for tomorrow's article! Until then 👋

Discussion (0)