DEV Community

loading...
Cover image for #30DaysofAppwrite : Create User Profiles
Appwrite

#30DaysofAppwrite : Create User Profiles

torstendittmann profile image Torsten Dittmann ・4 min read

Intro

#30DaysOfAppwrite is a month long event focused at 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 theseconcepts 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. It is important as we build upon the knowledge gained in Day 16 and plan and work with the database for our demo application.

Create A Profile

We will use the Profile Collection to give the users on our app a profile with public 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 limit the user to create only one profile for an account. For this, we need to first check if he already has a profile. Therefore we going to add a fetchUser() function that is going to list all documents in the Profiles Collection, with the user field equal to the ID of our account and limiting the amount of documents to 1.

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

Most important here is the part with [user=${id}] which will filter the requested documents by the user field that equals the passed 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 2 variables that represent the unique ID of our collections. Simply prepend following before the const api:

const profilesCollection = "[INSERT YOUR ID HERE]";
const postsCollection = "[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,
            {
                user: id,
                name: name,
            },
            ["*"],
            [`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 are prompting 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 his 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 also let the users create them! 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)

Forem Open with the Forem app