ระบบลงทะเบียน #04
วิชาการเขียนโปรแกรมบนอุปกรณ์เคลื่อนที่ (ดร.ธวัช)

PHP Myadmin

// ที่ต้องแก้ไข บรรทัด 1,2

CREATE DATABASE your-database;
USE your-database;

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL UNIQUE,
    password VARCHAR(255) NOT NULL
);                         

PHP API

// ที่ต้องแก้ไข บรรทัด 9,10

<?php
header("Content-Type: application/json");
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Allow-Headers: Content-Type");

$host = "localhost";
$user = "root";
$pass = "your-password (ถ้ามี)";
$db = "your-database";

$conn = new mysqli($host, $user, $pass, $db);
if ($conn->connect_error) {
    die(json_encode(['success' => false, 'message' => 'Database connection failed']));
}

$data = json_decode(file_get_contents("php://input"), true);
$action = $data['action'] ?? '';
$username = $data['username'] ?? '';
$password = $data['password'] ?? '';

if ($action === 'register') {
    $check = $conn->prepare("SELECT * FROM users WHERE username = ?");
    $check->bind_param("s", $username);
    $check->execute();
    $result = $check->get_result();

    if ($result->num_rows > 0) {
        echo json_encode(['success' => false, 'message' => 'Username already exists']);
    } else {
        $hashed_password = password_hash($password, PASSWORD_DEFAULT);
        $stmt = $conn->prepare("INSERT INTO users (username, password) VALUES (?, ?)");
        $stmt->bind_param("ss", $username, $hashed_password);
        if ($stmt->execute()) {
            echo json_encode(['success' => true, 'message' => 'Registration successful']);
        } else {
            echo json_encode(['success' => false, 'message' => 'Registration failed']);
        }
    }
} elseif ($action === 'login') {
    $stmt = $conn->prepare("SELECT * FROM users WHERE username = ?");
    $stmt->bind_param("s", $username);
    $stmt->execute();
    $result = $stmt->get_result();

    if ($row = $result->fetch_assoc()) {
        if (password_verify($password, $row['password'])) {
            echo json_encode(['success' => true, 'message' => 'Login successful']);
        } else {
            echo json_encode(['success' => false, 'message' => 'Invalid password']);
        }
    } else {
        echo json_encode(['success' => false, 'message' => 'User not found']);
    }
} else {
    echo json_encode(['success' => false, 'message' => 'Invalid action']);
}

$conn->close();
?>                     
        

Register.dart-Login.dart-Welcome.dart

// ที่ต้องแก้ไข บรรทัด 52,120

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primaryColor: const Color(0xFF004D40),
        scaffoldBackgroundColor: const Color(0xFFF1F8E9),
      ),
      home: LoginScreen(),
    );
  }
}

// ฟังก์ชันสร้าง TextField แบบมาตรฐาน
Widget _buildTextField(
    TextEditingController controller, String label, IconData icon,
    {bool isPassword = false}) {
  return TextField(
    controller: controller,
    obscureText: isPassword,
    decoration: InputDecoration(
      labelText: label,
      prefixIcon: Icon(icon, color: Color(0xFF00796B)),
      border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)),
    ),
  );
}

// หน้า Login
class LoginScreen extends StatefulWidget {
  @override
  _LoginScreenState createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
  final TextEditingController userController = TextEditingController();
  final TextEditingController passController = TextEditingController();

  Future<void> loginUser() async {
    final response = await http.post(
      Uri.parse('http://your-domain/your-folderyour-file.php'),
      headers: {'Content-Type': 'application/json'},
      body: jsonEncode({
        'action': 'login',
        'username': userController.text,
        'password': passController.text,
      }),
    );

    final data = jsonDecode(response.body);
    if (data['success']) {
      Navigator.pushReplacement(
        context,
        MaterialPageRoute(builder: (context) => HomeScreen()),
      );
    } else {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text(data['message'])),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 30.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text("ล็อคอิน", style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold, color: Color(0xFF00796B))),
              SizedBox(height: 30),
              _buildTextField(userController, "Username", Icons.person),
              SizedBox(height: 20),
              _buildTextField(passController, "Password", Icons.lock, isPassword: true),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: loginUser,
                style: ElevatedButton.styleFrom(
                  minimumSize: Size(double.infinity, 50),
                  backgroundColor: Color(0xFF00796B),
                  shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
                ),
                child: Text("Login", style: TextStyle(fontSize: 18, color: Colors.white)),
              ),
              SizedBox(height: 10),
              TextButton(
                onPressed: () {
                  Navigator.push(context, MaterialPageRoute(builder: (context) => RegisterScreen()));
                },
                child: Text("Create a new account", style: TextStyle(color: Color(0xFF00796B))),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

// หน้า Register
class RegisterScreen extends StatelessWidget {
  final TextEditingController userController = TextEditingController();
  final TextEditingController passController = TextEditingController();

  Future<void> registerUser(BuildContext context) async {
    final response = await http.post(
      Uri.parse('http://your-domain/your-folderyour-file.php'),
      headers: {'Content-Type': 'application/json'},
      body: jsonEncode({
        'action': 'register',
        'username': userController.text,
        'password': passController.text,
      }),
    );

    final data = jsonDecode(response.body);
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(data['message'])));
    if (data['success']) {
      Navigator.pop(context);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 30.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text("ลงทะเบียน", style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold, color: Color(0xFF00796B))),
              SizedBox(height: 30),
              _buildTextField(userController, "Username", Icons.person),
              SizedBox(height: 20),
              _buildTextField(passController, "Password", Icons.lock, isPassword: true),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: () => registerUser(context),
                style: ElevatedButton.styleFrom(
                  minimumSize: Size(double.infinity, 50),
                  backgroundColor: Color(0xFF00796B),
                  shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
                ),
                child: Text("Register", style: TextStyle(fontSize: 18, color: Colors.white)),
              ),
              SizedBox(height: 10),
              TextButton(
                onPressed: () {
                  Navigator.pop(context);
                },
                child: Text("Already have an account? Login", style: TextStyle(color: Color(0xFF00796B))),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

// หน้า Home
class HomeScreen extends StatelessWidget {
  void logout(BuildContext context) {
    Navigator.pushReplacement(
      context,
      MaterialPageRoute(builder: (context) => LoginScreen()),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Home", style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white)),
        backgroundColor: const Color(0xFF00796B),
        actions: [
          IconButton(icon: Icon(Icons.logout, color: Colors.white), onPressed: () => logout(context)),
        ],
      ),
      body: Center(
        child: Text("ยินดีต้อนรับ!", style: TextStyle(fontSize: 26, fontWeight: FontWeight.bold, color: Color(0xFF00796B))),
      ),
    );
  }
}