Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions apps/platform/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@
"reconnect": "Reconnect...",
"disconnect": "Disconnect"
},
"profile": {
"title": "Complete your profile",
"cancel": "Cancel",
"save": "Save",
"firstName": "First name",
"lastName": "Last name",
"email": "E-mail",
"mobile": "Phone number"
},
"round": {
"timeline": "Timeline",
"timelinePeriod": "August - September 2024",
Expand Down Expand Up @@ -168,9 +177,10 @@
"descriptionDesc": "What should be done? Why is that important? Why that location? Who all will benefit from this project?",
"descriptionPlaceholder": "Plant tall trees between existing small Oleander trees planted in this strip. Tall trees will provide needed shade for pedestrians, make the air cleaner and cooler, especially in the summer, and shield the entrance of the tunnel from the winds, while shielding the buildings from the noise from the tunnel.",
"descriptionError": "Write a little more about your project proposal.",
"nameTitle": "Your name and surname",
"nameDesc": "Enter your first and last name.",
"nameError": "Enter your name and surname.",
"firstNameTitle": "Your first name",
"firstNameError": "Enter your first name.",
"lastNameTitle": "Your last name",
"lastNameError": "Enter your last name.",
"proposerTitle": "Name of proposer",
"proposerDesc": "Provide the name of the individual citizen, group of citizens, or an organisation making the proposal. If you want to remain publicly unidentified, you can use a nickname.",
"proposerError": "Enter your name or organization name.",
Expand Down
16 changes: 13 additions & 3 deletions apps/platform/messages/hr.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@
"reconnect": "Ponovno prijavljivanje...",
"disconnect": "Odjavi"
},
"profile": {
"title": "Dovrši svoj profil",
"cancel": "Odustani",
"save": "Spremi",
"firstName": "Ime",
"lastName": "Prezime",
"email": "E-mail",
"mobile": "Broj mobitela"
},
"round": {
"timeline": "Raspored",
"timelinePeriod": "Kolovoz - Rujan 2024",
Expand Down Expand Up @@ -168,9 +177,10 @@
"descriptionDesc": "Što treba napraviti? Zašto je to važno? Zašto ta lokacija? Tko će sve imati koristi od ovog projekta?",
"descriptionPlaceholder": "Posadite visoka stabla između postojećih malih stabala oleandra posađenih u ovom području. Visoka stabla će pješacima stvarati potrebnu hladovinu, činiti zrak čišćim i hladnijim, posebno ljeti, štititi ulaz u tunel od vjetrova, a zgrade štititi od buke iz tunela.",
"descriptionError": "Napišite malo više o vašem prijedlogu projekta.",
"nameTitle": "Tvoje ime i prezime",
"nameDesc": "Navedite svoje ime i prezime.",
"nameError": "Unesite svoje ime i prezime.",
"firstNameTitle": "Tvoje ime",
"firstNameError": "Unesite svoje ime.",
"lastNameTitle": "Tvoje prezime",
"lastNameError": "Unesite svoje prezime.",
"proposerTitle": "Naziv predlagatelja",
"proposerDesc": "Navedite ime pojedinog građanina, grupe građana ili organizacije koja daje prijedlog. Ako želite ostati javno neidentificirani, možete koristiti nadimak.",
"proposerError": "Unesite vaše ime ili naziv organizacije.",
Expand Down
1 change: 1 addition & 0 deletions apps/platform/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"next-intl": "^3.17.2",
"react": "18",
"react-dom": "18",
"uuid": "^11.0.2",
"wagmi": "2.9.0",
"zod": "^3.23.8"
},
Expand Down
14 changes: 8 additions & 6 deletions apps/platform/src/app/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import { useState } from 'react';
import { useEffect, useState } from 'react';
import { useTranslations } from 'next-intl';
import Image from 'next/image';
import Link from 'next/link';
Expand All @@ -26,11 +26,13 @@ export default function Header() {
setIsOpen(!isOpen);
};

if (session) {
console.log(`Signed in as ${session.user?.name}`);
} else {
console.log('Not signed in');
}
useEffect(() => {
if (session) {
console.log('Signed in', session);
} else {
console.log('Not signed in');
}
}, [session]);

return (
<header className='border-b border-borderGray bg-white'>
Expand Down
65 changes: 65 additions & 0 deletions apps/platform/src/app/api/user/profile/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { z } from 'zod';
import { validateBody } from '@/lib/util/auth';
import { getUser, updateUser, User } from '@muqa/db';
import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import authOptions from '@/lib/next-auth/web3-provider/auth-options';
import { UpdateUserRequestSchema } from './schema';

export type UpdateUserRequestDTO = z.infer<typeof UpdateUserRequestSchema>;
export type UpdateUserResponse = {
success: boolean;
}

export interface UserProfileDTO {
firstName: string | null;
lastName: string | null;
email: string | null;
mobile: string | null;
}

class UserProfile implements UserProfileDTO {
firstName: string | null;
lastName: string | null;
email: string | null;
mobile: string | null;

constructor(user: User) {
this.firstName = user.firstName;
this.lastName = user.lastName;
this.email = user.email;
this.mobile = user.mobile;
}
}

export async function GET(req: NextRequest) {
const session = await getServerSession(authOptions);
if (!session?.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}

const user = await getUser(session.user as User);
if (!user) {
return NextResponse.json({ error: 'User not found' }, { status: 404 });
}

return NextResponse.json({ user: new UserProfile(user) });
}

export async function POST(req: NextRequest) {
const session = await getServerSession(authOptions);

if (!session?.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}

const body = await req.json();
const result = validateBody(body, UpdateUserRequestSchema);
if (result.error) {
return NextResponse.json({ error: result.error.message }, { status: 400 });
}

await updateUser(session.user as User, result.data as UpdateUserRequestDTO);

return NextResponse.json({ success: true });
}
8 changes: 8 additions & 0 deletions apps/platform/src/app/api/user/profile/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { z } from 'zod';

export const UpdateUserRequestSchema = z.object({
firstName: z.string().min(1, 'firstNameError'),
lastName: z.string().min(1, 'lastNameError'),
email: z.string().email('emailError'),
mobile: z.string().min(1, 'mobileError'),
}).strip();
10 changes: 8 additions & 2 deletions apps/platform/src/app/components/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,27 @@ import * as React from 'react';
import { twMerge } from 'tailwind-merge'

export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: string
variant?: string,
type?: 'button' | 'submit' | 'reset'
}

export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({
children,
className,
variant,
type = 'button',
...props
}: ButtonProps,
ref,
) => {
let buttonBg = variant === 'blue' ? 'bg-blue' : 'bg-primaryBlack';
buttonBg = variant === 'green' ? 'bg-green' : buttonBg;
const classes = `${buttonBg} flex items-center rounded-lg px-5 py-2 text-base font-normal leading-6 text-white hover:opacity-85 focus:outline-none`;
buttonBg = variant === 'link' ? 'bg-transparent' : buttonBg;

const buttonText = variant === 'link' ? 'text-gray' : 'text-white';

const classes = `${buttonBg} ${buttonText} flex items-center rounded-lg px-5 py-2 text-base font-normal leading-6 hover:opacity-85 focus:outline-none`;
return (
<button
ref={ref}
Expand Down
143 changes: 0 additions & 143 deletions apps/platform/src/app/components/MuqaConnectButton.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
export function AddressTooltip({ show, label, onMouseEnter, onMouseLeave }: {
show: boolean,
label?: `0x${string}`,
onMouseEnter?: () => void,
onMouseLeave?: () => void
}) {
const copyToClipboard = () => {
if (label) {
navigator.clipboard.writeText(label);
}
};

return (
<>
{show && !!label && (
<div className="absolute top-8 right-0 mt-2 w-max p-2 bg-gray-700 font-mono text-white text-sm rounded flex items-center"
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}>
<span>{label}</span>
<button
onClick={copyToClipboard}
className="ml-2 p-1 bg-gray-600 hover:bg-gray-500 rounded active:bg-gray-400 transition-colors duration-150 ease-in-out focus:outline-none focus:ring-2 focus:ring-gray-400"
title="Copy to clipboard"
>
<span className="transform inline-block transition-transform duration-150 ease-in-out active:scale-90">
📋
</span>
</button>
</div>
)}
</>
);
}
10 changes: 10 additions & 0 deletions apps/platform/src/app/components/MuqaConnectButton/LoadingIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { useAccount } from 'wagmi';

export function LoadingIcon() {
const { isConnecting } = useAccount();
return (
<>
{isConnecting && <div className="animate-spin h-5 w-5 mr-3 border-t-2 border-b-2 border-primary rounded-full"></div>}
</>
);
}
Loading