Multiple nextjs params with supabase for dynamic routing - next.js

I have started a small project (to learn Nextjs) with supabase and have hit a small roadblock. The basic overview is I have a table for stores (name, email, address, slug) and a table for socials (FK store => stores.id, name, url) which is linked via a foreign key on store => stores.id. Each store should have a separate page in the app where I will display their information and their social accounts.
I started by creating a dynamic route [id].tsx with:
export async function getServerSideProps({ params }) {
const { data: store, error } = await supabase
.from('stores')
.select('*, socials(*)')
.eq('id', params.id)
.single();
if (error) {
throw new Error(error.message);
}
return {
props: {
store
},
}
}
The above works just fine in my export default function Store ({store}) and I can see the stores information by going to localhost:3000/1 (only store set up currently). This does lead to my roadblock unfortunately. I would like the '1' to be the actual store slug (column in the stores table) like localhost:3000/lorem-ipsum but keep the relation between the two tables on the store id.
I understand that the params in my original example is id, and if I wanted the slug, I should rename my file to [slug].tsx and my params would be params.slug. Is it possible to utilize both the id and slug in my params and still have my query/route succeed?
I guess what I really want is to keep the relationship between my tables, but use the slug for querying the data (just for the url). I could make the FK the store slug, but I know it probably isnt the right move as the slug could change down the road.

id is just a variable for whatever is in the route. If you want the route to be using the slug, you just need to change the filter to search for the slug .eq('slug', params.id)

Related

Superbase db query from URL

I'm struggling to formulate a supabase db query from multiple tables, whilst using a value from a URL.
I have 3 tables (simplified)...
series > id, series
authors > id, name
books > id, title, series_id(fk), authors_id(fk)
I want to get a list of books in a series, along with the author and series name from the following URL...
app.com/series. i.e. app.com/harrypotter
I can get the series name using getServerSideProps, but struggling how to write my query to supabase. Every way I write it either gives me a NULL object or a 500 error.
I feel like I should be querying the books table and then be able to get the series and author names through the foreign keys. But the query that it's centred around is the series name, which is in the series table. So unsure of the db query to do it, or whether I should structure my db table's in a different way?
export async function getServerSideProps( context ) {
const { series } = context.query;
...
return {
props: {
...
}
};
}
Thanks for any help in advance!
Please ensure you have foreign keys set up, and then you can use Supabase to query foreign table examples (SQL join).
There needs to be more data to give an exact answer, but here are the relevant docs.
Supabase get a single record
Supabase select - not super obvious, but you need to click the button Query foreign tables
Supabase filters
I also included logs and a try/catch so you can see your exact errors and where your code is failing.
const Page = (props) => {
console.log(props)// logged to browser's console
return <>Your page<>;
}
export async function getServerSideProps( context ) {
try {
const { series } = context.query;
console.log("series", series); // ensure series is present and check if is an object
const { data, error } = await supabase.from('series')
.select(`
id,
title,
book (
title // you can also use `*` check out select all docs
author (
name
)
)
`)
.eq('id', series)
.limit(1)
console.log("error", error);
console.log("data", data);
return {
props: {
series: data
}
}
} catch (e) {
console.log(e);
}
}
export default Page;
Note: getServerSideProps logs will show up in your server's console (where you run npm dev) - not the browser's console. You should remove the console logs once you figure out what's happening.

How to extract params from received link in react native firebase dynamiclink?

I tried to migrate from react navigation deeplinks to firebase dynamic linking using this library (react-native-firebase).
I have set up everthing and links are being generated and received on the app. However, is there any way to extract the params sent in the link properly using this library?. Currenty this is my code for handling received link:
handleDynamicLink = () => {
firebase
.links()
.getInitialLink()
.then((url) => {
console.tron.log('link is ', url);
})
.catch((error) => {
console.tron.log(error);
});
};
The url received is
https://links.dev.customdomain.in/?link=products%2F1122
I want to extract the product id 1122 from the url. The only way for me right now is to parse the string and manually extract the relevant params. Unlike in react navigation deeplinks where I used to specify the path, like
Product: {
screen: Product,
path: 'customdomain/products/:slug',
},
Where the slug or id data used to pass as navigation param in the respective screen. Am I missing something? How can I pass mutliple params this way?
Point 2 in this link here says:
The response contains the URL string only.
This means that the firebase.links().getInitialLink() method does not return query parameters, at least as at the time of writing this (v5.5.5). To add your paramaters, you should use a URL with your query param as part of the URL. What I mean is this
Use https://links.dev.customdomain.in/link/products/1122
and use Regex to extract the product id which is of interest to you. This is what works for me and I hope it helps.

Firebase,iOS: Appending key-value pair into a child node

I have the following User Table structure in Firebase
As you can see in the user that I have opened, I have a Posts section, inside this post section holds the Id's all articles which have been posted by this user.
The issue I am facing is as follows:
When the user creates a new article it's saved within the Posts Table, after the save I return the newly generated ID which I then pass on to the user table, I trying to insert the newly created ID into the post section of the user, so I assumed the URL would be something like this:
Users/{UserId}/Posts
However all this does it create a new section called posts, it doesn't actually insert the record into the given area.
My code which isn't working is as follows:
let linkPost = [childautoID: true]
FIRDatabase.database().reference().child("Users/\(UserId)/Posts").child(UserId).setValue(linkPost)
FYI the two id's that are currently inside Posts I added manually.
I've also tried the following:
FIRDatabase.database().reference().child("Users/\(UserId)/Posts").setValue(linkPost)
However all this does it remove all existing Id's and then inserts the new id.
I prefer something like this. This automatically append the data without fetching first
FIRDatabase.database().reference().child("Users/\(UserId)/Posts").child(UserId).setValue(true)
To append a key-value pair in Firebase Database child node use this :-
Make a Firebase Database Reference to the Posts node of that currentUser FIRDatabase.database().reference().child("Users").child(FIRAuth.auth()!.currentUser!.uid).child("Posts")
Check if Posts node exists in your user's DB, If not then create one by :- parentRef.setValue([postId : "True"]) in else block.
But if Posts node does exist retrieve it as a NSMutableDictionary , set the new object to it, and then store the updated Dictionary to that node.
func storePostsToDB(postID :String!, userID : String! = FIRAuth.auth()!.currentUser!.uid){
let parentRef = FIRDatabase.database().reference().child("Users").child(userID).child("Posts")
parentRef.observeSingleEventOfType(.Value, withBlock: {(friendsList) in
if friendsList.exists(){
if let listDict = friendsList.value as? NSMutableDictionary{
listDict.setObject("True", forKey: postID)
parentRef.setValue(listDict)
}
}else{
parentRef.setValue([postID : "True"])
}
})
}
Calling the function:-
storePostsToDB("yourPostID")// If you want to store in the currentUser DB
storePostsToDB("yourPostID", userID : otherUserID)//If you want to store the post in some other users database with uid `otherUserID`

Fetch data for record edit page

I have a page that lets you edit user data. I'm using FlowRouter for the routing and it can be found on the route /employees/:id.
I need to update the detail form when data changes on the server and leave the route if it was deleted by other client.
I decided to use Tracker.autorun which informs me whenever the data changes. The previous user info is stored on the template so it's easy to tell if the record was deleted.
Template.UpdateEmployee.onCreated(function () {
const self = this;
self.subscribe('user', FlowRouter.getParam('id'));
self.autorun(function () {
const _id = FlowRouter.getParam('id');
const user = Meteor.users.findOne({_id});
if(!user && self.user)
FlowRouter.go('/employees');
self.user = user;
if(!user)
return;
user.email = user.emails[0].address;
$('.ui.form').form('set values',user);
});
});
And lastly in the onRendered callback I'm checking if the data was set on template as I believe not doing so could lead to data being available before the template is rendered and hence values wouldn't get set properly. Is this correct?
Template.UpdateEmployee.onRendered(function () {
if(this.user){
user.email = user.emails[0].address;
$('.ui.form').form('set values',user);
}
});
Are there any pitfalls to this solution?
I can see a couple drawbacks inherently. The first one is doing a find query on the client. Typically you would want to return data from the server using Meteor publish and subscribe.
The second is you are passing the key to find the data over the URL. This can be spoofed by other users for them to find that users data.
Lastly if you are doing a find on the user object, I assume you might be storing data there. This is generally bad practice. If you need to store user data with their profile, it's best to create a new collection and publish/subscribe what you need.

Angularfire generate new unique ID for non-email object

I'm making a web app using angularfire. I have a url for users at 'url.firebaseio.com/users'. I want to make another url to store chat-room type things at 'url.firebaseio.com/rooms'. When I create a new user using the $createUser() method, it stores the user's information under a unique ID created by $createUser() in the '/users' url. I want to do this with the new '/rooms' url, but I can't find a way to generate unique IDs in the same way without $createUser(). I can't use $createUser() because it requires an email address argument, and I just want to take in a name for the room and a password, all in an object under the unique ID for the room.
I can't think of any code to provide, so here's what a user looks like:
users: {
uniqueUserId: {
email: email#email.com,
name: name
}
}
And here's what I'd like a 'room' to look like:
rooms: {
uniqueRoomId: {
roomName: something
}
}
Is there a built-in way to do this? If not would it be best to generate IDs on my own?

Resources