How to dynamically change page titles and adapt login background design? (in v4)

Hello everyone, I cant find anything about that for the newest version online. Did anybody figure this out already? Login Page from Inferencer
42 Replies
kapa.ai
kapa.ai2y ago
Hey @l0zz1! I'm the kapa.ai support bot. I've searched through the docs to try to answer your question. :wave:
kapa.ai
kapa.ai2y ago
---------------------- To dynamically change page titles in refine v4, you can use the <Title> component from @pankod/refine. Unfortunately, there is no specific example in the provided extracts for v4. However, you can refer to the refine documentation (https://refine.dev/docs) for more information. For adapting the login background design, you can customize the login page by overriding the default login page and applying your own styles. Here's an example from the extracts:
import { useLogin } from "@refinedev/core";
import { Layout, Button, Row, Col } from "antd";
import Icon from "@ant-design/icons";

export const Login: React.FC = () => {
const { mutate: login, isLoading } = useLogin();

return (
<Layout
style={{
background: `radial-gradient(50% 50% at 50% 50%, #63386A 0%, #310438 100%)`,
backgroundSize: "cover",
}}
>
<Row
justify="center"
align="middle"
style={{
height: "100vh",
}}
>
<Col xs={22}>
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
marginBottom: "28px",
}}
>
<img src="./refine.svg" alt="Refine" />
</div>
<div style={{ display: "flex", justifyContent: "center" }}>
<Button
type="primary"
size="large"
icon={
<Icon
component={() => (
<img
alt={"ethereum.png"}
src="./ethereum.png"
/>
)}
/>
}
loading={isLoading}
onClick={() => login({})}
>
SIGN-IN WITH ETHEREUM
</Button>
</div>
</Col>
</Row>
</Layout>
);
};
import { useLogin } from "@refinedev/core";
import { Layout, Button, Row, Col } from "antd";
import Icon from "@ant-design/icons";

export const Login: React.FC = () => {
const { mutate: login, isLoading } = useLogin();

return (
<Layout
style={{
background: `radial-gradient(50% 50% at 50% 50%, #63386A 0%, #310438 100%)`,
backgroundSize: "cover",
}}
>
<Row
justify="center"
align="middle"
style={{
height: "100vh",
}}
>
<Col xs={22}>
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
marginBottom: "28px",
}}
>
<img src="./refine.svg" alt="Refine" />
</div>
<div style={{ display: "flex", justifyContent: "center" }}>
<Button
type="primary"
size="large"
icon={
<Icon
component={() => (
<img
alt={"ethereum.png"}
src="./ethereum.png"
/>
)}
/>
}
loading={isLoading}
onClick={() => login({})}
>
SIGN-IN WITH ETHEREUM
</Button>
</div>
</Col>
</Row>
</Layout>
);
};
In this example, the login page background is customized using the style prop of the <Layout> component. You can modify the styles according to your design preferences. ----------------------
Overview | refine
What is refine?
kapa.ai
kapa.ai2y ago
<@151783171510370305> kapa.ai is still learning and improving, please let us how it did by reacting below
genetic-orange
genetic-orangeOP2y ago
The title worked. But do I really have to copy the login page? cant I use the old one, but change the radiant color?
harsh-harlequin
harsh-harlequin2y ago
You need to swizzle AuthPage to customize https://refine.dev/docs/api-reference/mui/components/mui-auth-page/ Unfortunately you cant change radiant color with props.
genetic-orange
genetic-orangeOP2y ago
npm run refine swizzle
npm run refine swizzle
?
harsh-harlequin
harsh-harlequin2y ago
sorry wrong link https://refine.dev/docs/packages/documentation/cli/#swizzle bono im sorry you can customize AuthPage background like this
<AuthPage
type="updatePassword"
wrapperProps={{
style: {
background: "green",
},
}}
/>;
<AuthPage
type="updatePassword"
wrapperProps={{
style: {
background: "green",
},
}}
/>;
@l0zz1
genetic-orange
genetic-orangeOP2y ago
😂 😂 😂 😂 😂 😂 dont be sorry man you are always sorry u r doing this in ur free time, helping me out you are great! Thanks man, I'll test it in a bit
harsh-harlequin
harsh-harlequin2y ago
🙏🏻 thanks 😄
genetic-orange
genetic-orangeOP2y ago
works! Is there also any way to disable register? And how do you create a forgot password screen?
harsh-harlequin
harsh-harlequin2y ago
you can give registerLink={false}
genetic-orange
genetic-orangeOP2y ago
worked! I've also seen that in the docs... but the one thing I cant find is how to connect the forgot-password page to our supabase database, so that it sends out a reset password email. Is there any predefined prop for AuthPage or something like that? Or do we need to swizzle to do such thing?
harsh-harlequin
harsh-harlequin2y ago
what you mean when you say "connect" when forgot password page is submitted. its call authProvider's forgotPassword method
genetic-orange
genetic-orangeOP2y ago
well, it is already connected to our database, the login works. But we never defined a route or a function that tells supabase to send out a recovery email oh, let me check it wasnt defined, but I defined it:
forgotPassword: async ({ email }) => {
const { error } = await supabaseClient.auth.resetPasswordForEmail(
email, { redirectTo: "http://localhost:3000/update-password" }
);

if (error) {
return {
success: false,
error,
};
}

return {
success: true,
};
},
updatePassword: async ({newPassword}) => {
const { data, error } = await supabaseClient.auth.updateUser({password: newPassword,});

if (error) {
return {
success: false,
error,
};
}

return {
success: true,
};
}
forgotPassword: async ({ email }) => {
const { error } = await supabaseClient.auth.resetPasswordForEmail(
email, { redirectTo: "http://localhost:3000/update-password" }
);

if (error) {
return {
success: false,
error,
};
}

return {
success: true,
};
},
updatePassword: async ({newPassword}) => {
const { data, error } = await supabaseClient.auth.updateUser({password: newPassword,});

if (error) {
return {
success: false,
error,
};
}

return {
success: true,
};
}
Everything is working, but the updatePassword isnt. The page is loading and there are no undefined errors or such, but the password isnt changed. AND also, there are no success notifications, not even on the resetPasswordEmail 😄
harsh-harlequin
harsh-harlequin2y ago
hmm. i'm not familiar with this feature of supabase. i will debug and return you when is possible.
genetic-orange
genetic-orangeOP2y ago
any news on that? By the way: Should I copy my messages and questions and create a new post? Just so that other users can search for them, if they have the same question, so that u guys dont have to answer it 100 times. 😄
harsh-harlequin
harsh-harlequin2y ago
Please do that 🙏🏻 i need to discuss with the core team before answer this supabase update-password issue.
Omer
Omer2y ago
Hey @l0zz1 , Have you reviewed our Supabase example? All the features you mentioned are already integrated. Check it out at https://refine.dev/docs/examples/data-provider/supabase/
genetic-orange
genetic-orangeOP2y ago
I'm still working on some bug fixing, but I'll check it out in a bit. I already looked inside of the source code, but it was some time ago. Maybe it'll help now with my "new" knowledge 😄 I'll respond in a bit!
Omer
Omer2y ago
We can provide quick responses regarding Refine-related issues, but we cannot provide support for Supabase's API integration. Please use Supabase's Discord server for your Supabase API-related questions. Thank you for your understanding 🎯
genetic-orange
genetic-orangeOP2y ago
will do!
harsh-harlequin
harsh-harlequin2y ago
Hi @l0zz1, we have discovered some points that could potentially cause issues. When redirecting with the Supabase update-password link, a token is added to localStorage and a session is created. In our example, if the check function of the authProvider detects a session, the app is opened and we cannot go to update-password. See https://github.com/refinedev/refine/blob/master/examples/data-provider-supabase/src/App.tsx#L202. Because update-password page has authenticated wrapper. What should happen is to make an update-password request with the temporary session created by Supabase for reset-password. We have not yet found a solution that adheres to best practices. Please let us know if you find one.
genetic-orange
genetic-orangeOP2y ago
thank you! I'll tell you if I find something out, but this helps! Ok, just using the code from the example did the trick:
updatePassword: async ({ password }) => {
try {
const { data, error } = await supabaseClient.auth.updateUser({
password,
});

if (error) {
return {
success: false,
error,
};
}

if (data) {
return {
success: true,
redirectTo: "/",
};
}
} catch (error: any) {
return {
success: false,
error,
};
}
return {
success: false,
error: new Error("Update Password password failed"),
};
}
updatePassword: async ({ password }) => {
try {
const { data, error } = await supabaseClient.auth.updateUser({
password,
});

if (error) {
return {
success: false,
error,
};
}

if (data) {
return {
success: true,
redirectTo: "/",
};
}
} catch (error: any) {
return {
success: false,
error,
};
}
return {
success: false,
error: new Error("Update Password password failed"),
};
}
My guess is that the variable names do play a huge role here?
genetic-orange
genetic-orangeOP2y ago
but why are there no notifications? Shouldnt the AuthPage already have some type of notifications, without importing and installing antd? Isnt it possible to use those? :
No description
genetic-orange
genetic-orangeOP2y ago
Ok, I've seen that there are no success notification predefined for authprovider: auth.ts file:
export type AuthActionResponse = {
success: boolean;
redirectTo?: string;
error?: Error;
[key: string]: unknown;
};
export type AuthActionResponse = {
success: boolean;
redirectTo?: string;
error?: Error;
[key: string]: unknown;
};
So I guess you really have to use antd. But why are there success notifications when creating a new products for example? Those work without antd, right?
harsh-harlequin
harsh-harlequin2y ago
It can be work without antd if you have notificationProvider. there is no default success notification after auth operations. if you want, you can create your login page and you can open notification like this:
useLogin({
onSettled: (data) => {
if (data?.success) {
open?.({
message: "Login successful",
type: "success",
});
}
},
})
useLogin({
onSettled: (data) => {
if (data?.success) {
open?.({
message: "Login successful",
type: "success",
});
}
},
})
genetic-orange
genetic-orangeOP2y ago
I have a notificationProvider, but can I fire a notification in authProvider.ts? So that when a success: true is set, a notification is fired as well. Im not sure if I can use antd bc it could conflict with mui.
genetic-orange
genetic-orangeOP2y ago
I have that in the app.tsx. How can I use the component? Is that possible? I want to fire a Snackbar Notification when the passwordReset Email is sent. So it has to be inside of the authProvider.ts file. How can I user RefineSnackbarProvider to fire a Snackbar notification? I've seen it a couple of times, after a CREATE statement for example. But I can not find the code on how you did that.
Omer
Omer2y ago
You can directly use the 'open' function of the 'notificationProvider'. Please refer to this document. https://refine.dev/docs/api-reference/core/providers/notification-provider/#built-in-notification-providers
genetic-orange
genetic-orangeOP2y ago
Any fix for this?
No description
No description
genetic-orange
genetic-orangeOP2y ago
nothing?
harsh-harlequin
harsh-harlequin2y ago
hooks cannot call from regular javascript functions https://legacy.reactjs.org/docs/hooks-rules.html#only-call-hooks-from-react-functions you can try to call directly from notificationProvider
Rules of Hooks – React
A JavaScript library for building user interfaces
genetic-orange
genetic-orangeOP2y ago
directly from notificationProvider? What do you mean?
harsh-harlequin
harsh-harlequin2y ago
inside your authProvider, you can call notificationProvider.show()
genetic-orange
genetic-orangeOP2y ago
doesnt work on every import possible
No description
genetic-orange
genetic-orangeOP2y ago
is there another path I should import?
harsh-harlequin
harsh-harlequin2y ago
i will debug and return you
genetic-orange
genetic-orangeOP2y ago
thx!
harsh-harlequin
harsh-harlequin2y ago
with import { RefineSnackbarProvider} from "@refinedev/mui" we are using notistack@2 under the hood. we need to update this to use outside react component. issue: https://github.com/iamhosseindhv/notistack/issues/30#issuecomment-1171622850 i created notistack@3 example for you: https://codesandbox.io/s/trusting-hill-1voklb?file=/src/App.tsx:1386-1492 but with this example, we are using 2 snackbarprovider and this is not ideal. i suggest to create your notification provider until we updated notistack@2 to notistack@3 for example we implement react-toastify in this example: https://refine.dev/docs/api-reference/core/providers/notification-provider/#creating-an-notificationprovider but i don't know can u use react-toastify outside react. but i know u can use this https://react-hot-toast.com/docs/toast outside react they wrote this on the top of the page :D
Call it to create a toast from anywhere, even outside React. Make sure you add the <Toaster/> component to your app first.
Call it to create a toast from anywhere, even outside React. Make sure you add the <Toaster/> component to your app first.
genetic-orange
genetic-orangeOP2y ago
so I have to create a new notification provider with hot-toast?
harsh-harlequin
harsh-harlequin2y ago
Your choice to select notification system. Notistack@3 great library. React hot toast is great too. We will add notistack@3 update to our backlog but I can't give a release date without talking to the core team.